Skip to content

Use Symbol.hasInstance for instanceof narrowing, include constructor as part of class structural type #17360

Closed
@dead-claudia

Description

@dead-claudia

My proposal:

  • For instanceof expressions, if Symbol.hasInstance exists on the RHS, narrow the expression according to the method's return value.
  • For classes, implicitly add a type-level constructor prototype property which is typeof classConstructor, if such a property was not defined in the class body.
interface Foo { constructor: typeof Foo }
declare const Foo: {
    [Symbol.hasInstance](x: any): x is Foo
}

declare const Bar: {
    [Symbol.hasInstance](x: any): x is number
}

declare const foo: any
declare const bar: any

if (foo instanceof Foo) {
    // foo should be inferred as a Foo
}

if (bar instanceof Bar) {
    // bar should be inferred as a number
}

The rationale of this is that you can then (via compiler flag) by default define Symbol.hasInstance on constructors to type check against their return type (like for new () => T, defining [Symbol.hasInstance](x: any): x is T). This would mostly mitigate a certain unsoundness issue with classes, making the workaround a bit more difficult to do:

class Foo {
    bar: number = 1;
}

const foo1: Foo = new Foo() // Legal
const foo2: Foo = {bar: 2}  // No longer legal

// Making these illegal are out of scope of this proposal
const foo3: Foo = {
    constructor: Foo;
    bar: 2,
}
const foo4: Foo = new class {
    bar: number = 1
}

Notes:

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.SuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions