Scenario 1:
const myObject = {
foo: ['a', 'b', 'c']
}
type MyType1 = string[] extends [...infer Content] ? string : boolean
[...infer Content]
indicates that the tuple may have any number of elements. It has no restrictions.
Therefore, since string[]
is an array without a specified length (not a tuple), you will get string
.
Scenario 2
type MyType2 = string[] extends [infer First, ...infer Tail] ? string : boolean
[infer First, ...infer Tail]
specifies that your tuple must have at least one element because of First
.
Since you are checking myObject.foo
which is essentially string[]
, TypeScript cannot make any assumptions about the length of string[]
. string[]
is a mutable array.
Consider making 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
.
CONCLUSION
['a', 'b', 'c']
is inferred as string[]
because, as mentioned, it is an array and not a tuple.
If you want to treat it as a tuple, you can use ['a', 'b', 'c'] as const
.