Advanced Typescript: Inference

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:

1
2
3
4
5
6
7
8
9
10
11
> 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:

1
2
3
4
&gt; class Trigger { x = 0; y = 0 }
 
&gt; let g: InstanceType&lt;typeof Trigger&gt; = "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:

1
2
3
4
5
6
7
8
9
10
11
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.

8 responses

  1. […] the last part of this series, we talked about how you can infer types in Typescript. In this part, we’ll take a look at a related use-case: making the Typescript compiler happy […]

  2. […] the last part of this series, we talked about how you can infer types in Typescript. In this part, we’ll take a look at a related use-case: making the Typescript compiler happy […]

  3. […] the last part of this series, we talked about how you can infer types in Typescript. In this part, we’ll take a look at a related use-case: making the Typescript compiler happy […]

  4. […] the last part of this series, we talked about how you can infer types in Typescript. In this part, we’ll take a look at a related use-case: making the Typescript compiler happy […]

  5. […] the last part of this series, we talked about how you can infer types in Typescript. In this part, we’ll take a look at a related use-case: making the Typescript compiler happy […]

  6. […] the last part of this series, we talked about how you can infer types in Typescript. In this part, we’ll take a look at a related use-case: making the Typescript compiler happy […]

  7. […] the last part of this series, we talked about how you can infer types in Typescript. In this part, we’ll take a look at a related use-case: making the Typescript compiler happy […]

  8. […] the last part of this series, we talked about how you can infer types in Typescript. In this part, we’ll take a look at a related use-case: making the Typescript compiler happy […]

Leave a Reply to Advanced Typescript: Narrowing & Predicates – Furious BlackbirdCancel reply