You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Issue with Type guard when the variable is typed array with specified lengths #8473
Expected behavior:
On line 8 (inside the else if block), the array variable should be of type [number], and on line 11 (inside the else block) the array variable should be of type [number, number].
Other option is: in both code blocks, array should be any of the two types - [number] | [number, number].
In this case there should be a compile error on line 11 with the following message:
[ts] Type '[number] | [number, number]' is not assignable to type '[number, number]'. Type '[number]' is not assignable to type '[number, number]'. Property '1' is missing in type '[number]'.
And the workaround will be to explicitly cast value:
array=<[number,number]>value;
Actual behavior:
In both code blocks array is [number], and on line 11 there is a compile error:
[ts] Type '[number]' is not assignable to type '[number, number]'. Property '1' is missing in type '[number]'.
In this case we can explicitly cast value as shown above, but the error message is wrong.
If we replace value.length === 1 with isSingleLength(value), the behavior is the same.
functionisSingleLength<T>(value: T[]): value is [T]{returnvalue.length===1;}
Despite the apparent correct behavior, I don't believe that
if(value.length===1)
is actually used as a guard here (I'm not aware of length assertions being used to narrow between unions of tuple types). It seems like the compiler would have inferred the same type even if the first else if would be replaced by a plain else:
letvalue: number|[number]|[number,number];if(!Array.isArray(value)){value;// type of 'value' is 'number'}else{value;// type of 'value' is '[number]'}
This may have (possibly unintentionally) uncovered a different issue though: that perhaps in the 'else' block value should get type [number] | [number, number] instead of just [number].
I have verified the same erroneous inference would also happen in the case where the first if would not use negation in the condition (i.e. if (Array.isArray(value))).
length is not used to narrow types. tuples are not guaranteed to have a fixed length. Tubles are just arrays, with known types for the first n elements. consider:
Activity
malibuzios commentedon May 5, 2016
(I'm using version
1.9.0-dev.20160505)Despite the apparent correct behavior, I don't believe that
is actually used as a guard here (I'm not aware of length assertions being used to narrow between unions of tuple types). It seems like the compiler would have inferred the same type even if the first
else ifwould be replaced by a plainelse:This may have (possibly unintentionally) uncovered a different issue though: that perhaps in the 'else' block
valueshould get type[number] | [number, number]instead of just[number].I have verified the same erroneous inference would also happen in the case where the first
ifwould not use negation in the condition (i.e.if (Array.isArray(value))).mhegazy commentedon May 5, 2016
length is not used to narrow types. tuples are not guaranteed to have a fixed length. Tubles are just arrays, with known types for the first n elements. consider: