Home > front end >  Usage of typescript infer does not work for array
Usage of typescript infer does not work for array

Time:09-21

I have the following typescript code:

const myObject = {
  foo: ['a', 'b', 'c']
}

type MyType = typeof myObject.foo extends [...infer Content] ? string : boolean

And MyType results in type string as expected.

But if I change the code like this:

...

type MyType = typeof myObject.foo extends [infer First, ...infer Tail] ? string : boolean

MyType now becomes boolean. Why?

Why does it extend in the first case but not in the latter?

CodePudding user response:

First use case:

const myObject = {
  foo: ['a', 'b', 'c']
}

type MyType1 = string[] extends [...infer Content] ? string : boolean

[...infer Content] - means that tuple might have 0 or 1 or more elements. No restriction at all.

Hence, since string[] is an array without explicit length (is not a tuple) you are getting string.

Second case


type MyType2 = string[] extends [infer First, ...infer Tail] ? string : boolean

[infer First, ...infer Tail] - mean that your tuple should have at least one element, because of First. Because you are checking myObject.foo which is basically stirng[], TS is not allowed to make any assumptions about string[] length. string[] is a mutable array.

Try to make myObject immutable.

const myObject = {
  foo: ['a', 'b', 'c']
} as const;

// string
type MyType1 = typeof myObject.foo extends readonly [...infer Content] ? string : boolean
//string
type MyType2 = typeof myObject.foo extends readonly [infer First, ...infer Tail] ? string : boolean

Playground

Now, both MyType's are strings.

SUMMARY

['a', 'b', 'c'] is infered as string[] because, like I said it is an array and not a tuple.

If you want it to make a tuple, you can use ['a', 'b', 'c'] as const.

  • Related