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?
mengjie guo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
4
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.