-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Closed as not planned
Closed as not planned
Copy link
Labels
Not a DefectThis behavior is one of several equally-correct optionsThis behavior is one of several equally-correct options
Description
π Search Terms
filter type guard failing to narrow tuple supertype
π Version & Regression Information
- This is the behavior in every version I tried
β― Playground Link
π» Code
import { expectType } from "ts-expect";
declare function Tuple0IsNumberOrString(tuple: [unknown]): tuple is [number | string]
declare const t: [number | null] // t[0] is string | number
if (Tuple0IsNumberOrString(t)) {
t[0] // predictably the type guard narrows t[0] to number
}
// but filter fails to narrow
const list = [t]
const filtered = list.filter(Tuple0IsNumberOrString)
const f = filtered[0]![0] // number | null
// strangely if the typeguard is changed, narrowing now works
declare function Tuple0IsNumber(tuple: [unknown]): tuple is [number]
const filtered2 = list.filter(Tuple0IsNumber)
const f2 = filtered2[0]![0] // numberMore 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
Metadata
Metadata
Assignees
Labels
Not a DefectThis behavior is one of several equally-correct optionsThis behavior is one of several equally-correct options