1

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?

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.