Search Terms
- instanceof generic
- narrow instanceof
Suggestion
The following code has a rather unexpected behavior today:
classParent<T>{x: T;}classChild<S>extendsParent<S>{y: S;}functionexample(obj: Parent<number>){if(objinstanceofChild){constchild=obj;}}The narrowed type that child gets is Child<any>.
I'm requesting that the type instead gets narrowed to Child<number>, which is what I originally assumed would happen.
My proposal is, in general, to infer the type arguments to the narrowed-to class type whenever they can be determined from the original type.
Precise Behavior
Consider the following code today:
constx: P= ...;if(xinstanceofC){x;}Today, if C is a generic class, x gets the narrowed type C<any, any, any, ...>; otherwise it just gets the type C.
My proposal is to consider the following piece of code, and use it to inform
Imagine that C has a no-argument constructor. Then the following piece of code is valid today:
functiononlyP(c: P){ ... }onlyC(newC());in order to make it valid, the compiler infers type arguments for C that make it into a subtype of P. My proposal is to use the same strategy to infer the type arguments for C in an instanceof narrowing.
Consider the following examples today, and their corresponding instanceof narrowings:
functionex1(x: Parent<string>){}ex1(newChild());// inferred arguments: <string>functionex2(x: Parent<number|string>){}ex2(newChild());// inferred arguments: <number | string>functionex3(x: Parent<number>|string){}ex3(newChild());// inferred arguments: <number>functionex4(x: Parent<number>|Parent<string>){}ex4(newChild());// inferred arguments: Child<number | string>// Note: the above errors, because it Child<number|string> actually fails to be a subtype of// Parent<number> | Parent<string>.// We can either choose to infer Child<any> in this case, or use the (incorrect, but more-precise)// inference Child<number | string>.Examples
The original use-case I had in mind was roughly the following:
abstractclassObtainer<T>{__phantom: T=nullasT;}abstractclassFetcher<T>extendsObtainer<T>{publicabstractfetch(): Promise<T>;}abstractclassDependency<T,D>extendsObtainer<T>{publicabstractdependencies(): Obtainer<D>;publicabstractcompute(got: D): T;}asyncfunctionobtain<T>(obtainer: Obtainer<T>): Promise<T>{if(obtainerinstanceofFetcher){// obtainer: Fetcher<T>// currently, it's a Fetcher<any>returnawaitobtainer.fetch();}if(obtainerinstanceofDependency){// obtainer: Dependency<T, any>// currently, it's a Dependency<any, any>constdependencies=obtainer.dependencies();returnobtainer.compute(awaitobtain(dependencies));}thrownewError("not implemented");}(note: there's still one extraneous any in the above, since the D parameter cannot be inferred)
Checklist
My suggestion meets these guidelines:
Also, I am interested in contributing this change if it's approved!
Search Terms
Suggestion
The following code has a rather unexpected behavior today:
The narrowed type that
childgets isChild<any>.I'm requesting that the type instead gets narrowed to
Child<number>, which is what I originally assumed would happen.My proposal is, in general, to infer the type arguments to the narrowed-to class type whenever they can be determined from the original type.
Precise Behavior
Consider the following code today:
Today, if
Cis a generic class,xgets the narrowed typeC<any, any, any, ...>; otherwise it just gets the typeC.My proposal is to consider the following piece of code, and use it to inform
Imagine that
Chas a no-argument constructor. Then the following piece of code is valid today:in order to make it valid, the compiler infers type arguments for
Cthat make it into a subtype ofP. My proposal is to use the same strategy to infer the type arguments forCin aninstanceofnarrowing.Consider the following examples today, and their corresponding
instanceofnarrowings:Examples
The original use-case I had in mind was roughly the following:
(note: there's still one extraneous
anyin the above, since theDparameter cannot be inferred)Checklist
My suggestion meets these guidelines:
--strictGenericNarrowingflag.Also, I am interested in contributing this change if it's approved!