type TypeOfOptions = typeof options[number] // (string | number)[]
type IsTypeOfOptionsSubsetOfSomeTuple =
TypeOfOptions extends SomeTuple ? true : false // false is not assignable to SomeTuple
It meansTypeOfOptions
is just more general type then SomeTuple
and naturally cannot be used as SomeTuple
, this is exactly why you do have the error. You want [string, number]
you get by automatic inference (string | number)[]
, clearly not the same.
Why its more general because TS type inference works like that, we can change the behavior by assert our type to more specific by as
or :
or make value constructor which will do that.
Below few possible options how to change the initial inference:
// value constructor
const makeOptions = (...a: SomeTuple[]): SomeTuple[] => a
const options1 = makeOptions(
['first', 1],
['second', 2],
) // a is SomeTuple[]
// using :
const options2: SomeTuple[] = [
['first', 1],
['second', 2],
];
// using as
const options3 = [
['first', 1],
['second', 2],
] as SomeTuple[]
foo(options1) // ok
foo(options2) // ok
foo(options3) // ok
Additional note about question in the comment. Generally type SomeTuple
is a specification of type TypeOfOptions
, it means that if you have value which is TypeOfOptions
it can be also SomeTuple
but does not must be. Lets check if such relation is true:
type IsSomeTupleSubsetOfTypeOfOptions = SomeTuple extends TypeOfOptions ? true : false // true
So yes SomeTuple
is specific variant of TypeOfOptions
. It means we can assert type of TypeOfOptions
into SomeTuple
saying we are narrowing to this specific case. But if we do that - TS will validate the value to the narrowed type right away, if its match, type assertion is successful.