Closed as not planned
Closed as not planned
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] // number
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