-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Closed
Labels
Working as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug
Description
TypeScript Version: 4.0.2
Search Terms: type narrowing, intersection, property, any, type loss, property widening, generic type narrowing, instanceof, typeof
Code
This shows how ts fails to preserve generic types after narrowing the type with instanceof:
class A<T> {
constructor(public value: T) {}
}
const fn = <T>(value: T) => {
if (value instanceof A) {
return value;
}
return undefined;
};
const fn = wrap(new A(42));
if (test) {
type valueType = typeof test.value; // any
}The inferred result of wrap is T & A<any>. Because of any's (or unknown's) widening nature, there is type information loss (widening to unsafe any on properties).
Expected behavior:
Instead of using & in the inferred result, could we use a conditional type instead? At the moment, I do this by hand:
class A<T> {
constructor(public value: T) {}
}
const fn = <T>(value: T) => {
if (value instanceof A) {
return value as any as Extract<T, A<any>>;
}
return undefined;
};
const test = fn(new A(42));
if (test) {
type valueType = typeof test.value; // number
}Actual behavior:
TypeScript creates intersections, causing generic property type loss.
Related Issues:
Related from far #37993
Metadata
Metadata
Assignees
Labels
Working as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug