-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Closed
Labels
Design LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixed
Description
Bug Report
π Search Terms
recursive nested conditional type guard function
π Version & Regression Information
- This changed between versions 5.1.0-dev.20230303 and 5.1.0-dev.20230304
β― Playground Link
Playground link with relevant code
π» Code
type NestedRecord<K extends string, V> =
K extends `${infer K0}.${infer KR}` ?
{ [P in K0]: NestedRecord<KR, V> } :
{ [P in K]: V };
declare function guardPathX<T>(x: T): x is T & NestedRecord<'a.b.x.c', string>;
declare function guardPathY<T>(x: T): x is T & NestedRecord<'a.b.y.c', string>;
function foo(obj: {}) {
if (guardPathX(obj) && guardPathY(obj)) {
obj.a.b.x.c.toUpperCase(); // okay
obj.a.b.y.c.toUpperCase(); // <-- error, what?
}
}
π Actual behavior
obj
has been narrowed only to {a:{b:{x:{c: string}}}}
.
π Expected behavior
obj
should be narrowed to {a:{b:{x:{c: string}}}} & {a:{b:{y:{c: string}}}}
.
This is a weird one. Seems to be caused by the recursive NestedRecord
utility type (if I replace that with hardcoded types it works) interacting with multiple type guard applications. Probably hitting some limit somewhere where it gives up? Or an inaccurate variance shortcut? Not sure. Anyway this broke some Stack Overflow answer I was working on and it would be nice to know what's up with it.
Metadata
Metadata
Assignees
Labels
Design LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixed