So in part 1 of this series, we looked at how the typeof
operator can be used to infer the Typescript type of an object. There’s a bunch more ways to infer types, and it makes working with Typescript pretty interesting as you can make the type inference do the work for you. Here’s a few of them:
Infer the ReturnType of a function
Works like you’d expect:
> function isEmpty(s: string | null | undefined) { return s === "" || s === null || s === undefined } > let a: ReturnType<typeof isEmpty> > a = "hello" [eval].ts:3:1 - error TS2322: Type '"hello"' is not assignable to type 'boolean'. 3 a = "hello" ~ undef
Note the slightly weird construction: ReturnType <typeof isEmpty>
. That’s because ReturnType (just like all Typescript types) expects a type as a parameter, and not a value.
Infer the type of an instance from the Class Name
Just like ReturnType
, there’s also InstanceType
:
> class Trigger { x = 0; y = 0 } > let g: InstanceType<typeof Trigger> = "hello" [eval].ts:14:5 - error TS2322: Type '"hello"' is not assignable to type 'Trigger'.
Infer the type of Props of a React Component
Here’s a code fragment from Reactist test suite that illustrates this:
const getAvatar = ( props?: Omit<React.ComponentProps<typeof Avatar>, 'user'> & { user?: { name?: string; email: string } } ) => ( <Avatar user={{ name: 'Henning Mus', email: 'henning@doist.com' }} size="xl" {...props} /> )
As you can see React.ComponentProps
works pretty much like ReturnType
, so you don’t really need to export Props from a component ever. (h/t Janusz)
Typescript has far more complex inference (the infer keyword comes to mind), but this is good enough to start and really simplifies a lot of use-cases, and avoids unneeded type exports from a library.
One thought on “Advanced Typescript: Inference”