-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Filter with a type guard fails to narrow when the type guard's predicate is a tuple supertype #59054
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
This depends on the filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; With your type predicate you end up with: T // [number | null]
S // [number | string] This |
The second overload here allows the typeguard the work. interface Array<T> {
filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
filter<V, S extends V>(predicate: (value: V, index: number, array: T[]) => value is S, thisArg?: any): (T&S)[];
} The problem though is that T and may not be assignable to V, leading to unsafety. V needs a constraint that it is a supertype of T. e.g. type AllowedV<V, T> = T extends V ? V : 'not allowed'
declare global {
interface Array<T> {
filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
filter<V, S extends V>(predicate: (value: AllowedV<V, T>, index: number, array: T[]) => value is S, thisArg?: any): (T&S)[];
}
} TS Playground with supertype constraint Seems like we need supertype constraints to make progress on this #14520 |
You would need to write this as declare function Tuple0IsNumberOrString<T>(tuple: [T]): tuple is [T & (number | string)] |
This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
π Search Terms
filter type guard failing to narrow tuple supertype
π Version & Regression Information
β― Playground Link
Playground Link
π» Code
More examples on the playground
π Actual behavior
[number | null] & [number | string]
generally gives a result of[number]
, but when a type guard is used with filter (specifically), the result is not the expected type of[number][]
, but rather the input type of[number | null][]
.The problem occurs when the type guard's type assertion is a supertype of the expected item result type
[number]
, but goes away if the type assertion is the same type or a subtype, i.e.[number]
or[5]
. The problem does not occur without the tuple wrapper.π Expected behavior
The filter result should be
[number][]
Additional information about the issue
No response
The text was updated successfully, but these errors were encountered: