Closed
Description
TypeScript Version: 3.2.1-insiders.20181128
Search Terms: type guard this generic
Summary
In a class MyClass<T>
, a type guard of the form this is MyClass<T & Foo>
should constrain T
to extend Foo
.
Alternative
It might make more sense to instead allow type guards on generic parameters; eg, isFoo(): T is Foo
.
Code
class FooBuilder<TWith> {
private bar?: number;
private qux?: number;
private whatIsTWith?: TWith
private hasBar(): this is FooBuilder<TWith | WithBar>{
return !!this.bar;
}
private hasQux(): this is FooBuilder<TWith | WithQux>{
return !!this.qux;
}
public specify(options: Options<TWith>) {
if (this.hasBar()) {
options.bar;
this.whatIsTWith;
}
if (this.hasQux()) {
options.qux;
}
}
}
class WithBar { private noStructuralTyping: undefined; }
class WithQux { private noStructuralTyping: undefined; }
type Options<TWith> =
(WithBar extends TWith ? { bar: string } : {})
& (WithQux extends TWith ? { qux: string } : {});
// Usage:
new FooBuilder<WithBar | WithQux>().specify({ bar: '', qux: '' });
Expected behavior:
Inside if (this.hasBar())
, TWith
should be constrained to extend WithBar
and options.bar
should exist.
Actual behavior:
options
still has no properties.
With stricter compilation options, this.whatIsTWith
has conflicting definitions.