I have the following type:
type GetNum<T extends number[] | number> = T extends number ? T : T['length']
But it generates a compilation error:
Type '"length"' cannot be used to index type 'T'.
Why is that? The generic type parameter is constrained to be either a number
or number[]
array. In the true arm of the conditional type, I check whether it's a number
, so in the false arm the type should be narrowed to number[]
, and therefor have a length
property. Yet, I get the error mentioned above.
Why doesn't this work? Is there any relevant information for reference?
You could get that to compile if you reverse the condition in your conditional type:
type GetNum<T extends number[] | number> = T extends number[] ? T['length'] : T;
Sinces types don't direct runtime behavior, it doesn't really matter all that much though. T['length']
just resolves to number
so, you could just have written:
type GetNum<T extends number[] | number> = T extends number ? T : number;
There are a number of issues on the TypeScript GitHub repository that are related: #21937, #29188, #48710, #51040, and probably others. Since there's an easy workaround, the TypeScript team doesn't seem to be in a rush to address this, as this comment expresses:
In the general case, it's not sound to narrow the false arm of a conditional type. When the check type fully subsumes one of the constraint's union constituents we could, but that logic just isn't present right now. Regardless, the workaround is straightforward.