Skip to content

Type Guards on this should affect type parameters #28889

Closed
@SLaks

Description

@SLaks

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.

Playground Link: Link
Related Issues: #14817

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions