Skip to content

[TS 5.4.0-beta] instaceof narrowing impacted by prototype propertyΒ #57397

Closed as not planned
@acutmore

Description

@acutmore

πŸ”Ž Search Terms

instanceof, narrowing, prototype

πŸ•— Version & Regression Information

  • This changed between versions 5.3.3 and 5.4.0-beta.
  • This changed on 5.4.0-dev.20231130 (commits)

⏯ Playground Link

https://www.typescriptlang.org/play?target=99&ts=5.4.0-dev.20231130#code/CYUwxgNghgTiAEkoGdnwOoEtgHMQBd4BvAKHnNGXxgHsBPACgEoAueANxuwG4SBfEiVBI4iGgDsqGbHnwBhCVRgBXMPhow2pcuXEgA7szZZcBXgKHhoosIsIBZEOOUnZc6Ki1kdew62LeOjqYyI7OADIh+GwARjQ0ECBQ4rxBfPAAZNKm+Kk6AA606vh0+SBsJWU0AGbZbnYqahrc8AD0rfAAPAC03fBwALY07JjiOPD4ABYh8FCc2GggMLQw-LwklQhhLjIE8AC88ACSkvjJYCAAKqUgnZs18NuuBO4oyAB868LWCLanj04djkKjcHk9dvIPGgstofAYjADnM98GtBO10RjMVjsTjcXj0YJEoQ-vgnNFEUDZPAAD7wZTiUDVUYgYC8b6wX52DjGCHrTC1BjseCjKjnEBgwHIpgBILkElkg4cFrtLq9eC+eBLFbC8TwACsADoACwGgAM3RiBCg-EEIAAHvkNIQiAIgA

πŸ’» Code

(reduced down from large repo as best I could)

declare class Widget {
   destroy(): void;
}

declare const WidgetConstructor: {
    new(): Widget;
}

declare const MenuWidgetClass: {
    new(): {
        isMenuList: boolean;
    } & Widget;
    prototype: typeof WidgetConstructor; // <-- removing this avoids error
};

type MenuWidget = InstanceType<typeof MenuWidgetClass>;

declare const MenuWidget: typeof MenuWidgetClass & {
    new(): MenuWidget
};

/////////////////////////////////////////////////////////

let content: MenuWidget | undefined;
declare const v: Widget;

if (v instanceof MenuWidget) {
      content = v; // <-- new error in 5.4.0-beta
}

New behavior

TypeScript 5.4.0-beta appears to be consulting the .prototype property of the type in a way that it wasn't before resulting in the instanceof narrowing to narrow to the base class.

Previous behavior

The code in 5.3.3 was expecting the instanceof to narrow to the return type of the function being consulted.

Additional information about the issue

Note: this is more of a change report than a bug report, as I don't think this was announced in the 5.4.0-beta breaking changes. I suspect the change is an improvement and is catching a potential issue that was previously unsafe.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Not a DefectThis behavior is one of several equally-correct options

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions