DEV Community

Pavel M
Pavel M

Posted on

TypeScript ValidityState

const input: HTMLElement = e.target
const validity: ValidityState = input.validity
setValidity(validity.valid)
Enter fullscreen mode Exit fullscreen mode

I'm just getting into typescript and having a problem with the ValidityState API: the second line gets a red squiggly underline with Unsafe assignment of an 'any' value.

What's the proper course of action here?

Discussion (5)

Collapse
harry0000 profile image
harry

HTMLElement does not have readonly validity: ValidityState property. Only the following elements have that property.

github.com/microsoft/TypeScript/bl...

  • HTMLButtonElement
  • HTMLFieldSetElement
  • HTMLInputElement
  • HTMLObjectElement
  • HTMLOutputElement
  • HTMLSelectElement
  • HTMLTextAreaElement

If you are using React, you can write as follows:

TS playground link

const input: React.FC = () => {
    return (
        <input onChange={(e) => {
          const input: HTMLInputElement = e.target
          const validity: ValidityState = input.validity
          setValidity(validity.valid)
        }}/>
    )
}
Enter fullscreen mode Exit fullscreen mode

or

const input: React.FC = () => {
    return (
        <input onChange={(e) => {
          // e: React.ChangeEvent<HTMLInputElement>
          setValidity(e.target.validity.valid)
        }}/>
    )
}
Enter fullscreen mode Exit fullscreen mode
Collapse
harry0000 profile image
harry

Or if you wanted to define a handler function, you can write as follows:

const handler: (e: React.ChangeEvent<HTMLInputElement>) => void = (e) => {
    // ...
}
Enter fullscreen mode Exit fullscreen mode

or

const handler = (e: React.ChangeEvent<HTMLInputElement>): void => {
    // ...
}
Enter fullscreen mode Exit fullscreen mode
Collapse
lukeshiru profile image
Luke Shiru

You can also use ChangeEventHandler:

const handler: ChangeEventHandler<HTMLInputElement> = event => {
  // handle event
}
Enter fullscreen mode Exit fullscreen mode

Tho generally, if you inline the handler, you don't need to type it because the type is inferred automatically.

Collapse
lukeshiru profile image
Luke Shiru

A few recommendations that might help:

  • Use currentTarget instead of target. The target property of Event points to the element that triggered the event, but currentTarget points to the element that has the event listener, which is almost always what you actually want.
  • In TS you don't need to type every single thing, if you type one thing, everything else can be inferred automatically:
// We type `currentTarget` as `HTMLInputElement`
const input = event.currentTarget as HTMLInputElement;

// Then everything else is correctly inferred, not types needed:
const { validity } = input;
setValidity(validity.valid);
Enter fullscreen mode Exit fullscreen mode

You could also simplify it quite a bit if you only need the validity.valid value:

const { validity: { valid } } = event.currentTarget as HTMLInputElement;
setValidity(valid);

// or
setValidity((event.currentTarget as HTMLInputElement).validity.valid);
Enter fullscreen mode Exit fullscreen mode
  • Ideally (idk what framework or library are you using), you should have your event typed so the type of currentTarget and target are inferred. In React that's done for you with the *EventHandler types, with Angular you have other solutions, but it depends on what you're using.

Hope that helps a little.
Cheers!

Collapse
vkrms profile image
Pavel M Author

Thanks a bunch! It helped a lot.