Skip to content

Instanceof Type Inference Doesn't Take Generic Defaults Into AccountΒ #60602

Closed as not planned
@joeedh

Description

@joeedh

πŸ”Ž Search Terms

inference, generic, parameter, default

πŸ•— Version & Regression Information

Behavior is the same in all version I tried.

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.7.2#code/PQKgBApgzgNglgOwC4FoAmcoEMBGMJgjABQxEAHgA4D2ATkmEgJ6UECiAbhMgJIIAWEWnCQARCADMsAVxgMAvGADejFhABcYBBC60wAXwDcZKnQbNWYTtyR9BwpABU1YRSosaw0hAGsE1AHcEA2NiDzAAcQgka2QoAB5YpChIciRuNBSkuyERZ1YAPlcrLjiAbQAiDwqAXVT0hEywKCRhBABzYjAwAH4SmyhK6pqusE1tXWMKGnpVSySomNLkxPqMrOWch3yIIsVFpIS2AqnTWfCtkUP4xzXGlJa29oAaKzum7IFcpzU95VGPJpbgAfSLRa7HYxGUjTMxgADGMCwUBSACFkRBEssUhQGk1Hoh2sUCR0ikpRhAALZXZYACh0Nk0hwAlMp9MR2SYZgxEciUgBBeKjQ7vDY2S4-SyKT72ETiKSyJDEIq49ZgdFQTELcHY+IS64VajaCpgUFVALUCqvQ4FW1smFnHlIlFgADCWIGov6vC+2xc0s2vrlkhkchVaTVgtG+t1VX4tAgEBNZok1GktCt3uSBWV9uI8KNLQRxW0ATdtOZxgLCCLOAxmg1BEU8NC8IAdFSaTZaXGE0nK8Q4BIwLS65qwIgWlgEPCINRh67WeTusBgM1+GmYGgwDgCNPILRaHRnqNV3MCIgJEJuLOwFI4Pht0hqF5x+1uLl4WBKFhaFhKdEQinmuaAhoqhjnmA847hiE4pO605MDm3RjhAHbUks3a9v2oQrmu0zwPCIgIsiDBoNQ0AkdI477kIR60KM1ZFvCpHFKhYDIm6xjdCxLToV2yA9kg8Y4RyxBAA

πŸ’» Code

/* eslint-disable */

// The idea here is to propagate a primitive string union of event types
// down a class hierarchy.  The weird boilerplate is to keep TS 
// from automatically inferring to `string`.

export type EventInheritDefault = { type: never };
export type EventInheritType = { type: unknown };

type GetEvents<Events extends EventInheritType> = Events["type"] extends string
  ? Events["type"]
  : never;
export type EventGetEvents<E extends EventInheritType> = GetEvents<E>;
export type InheritEvents<T extends string, E extends EventInheritType> = {
  type: T | GetEvents<E>;
};

export class Base<Events extends string = string> {
  emitEvent(event: Events) {}
}

export class A<
  Events extends EventInheritType = EventInheritDefault
> extends Base<EventGetEvents<InheritEvents<"one" | "two", Events>>> {}

export class C<Events extends EventInheritType = EventInheritDefault> extends A<
  InheritEvents<"three" | "four", Events>
> {}

const c = new C();
const base: Base = c;

c.emitEvent("three");
if (base instanceof C) {
  // should be an error
  base.emitEvent("thre");

  // explicit cast does cause an error
  const cast = base as C;
  cast.emitEvent("thre");
}

πŸ™ Actual behavior

The instanceof check resolved to C<any> instead of using the generic parameter's default.

πŸ™‚ Expected behavior

The instanceof check should not resolve to C<any> and should produce an error when calling base.emitEvent("thre")

Additional information about the issue

It seems odd that an instanceof check would produce a different result then a cast. The following code actually does work correctly:

const C2 = C as {new(): C}
if (base instanceof C2) {
  // this now errors as expected
  base.emitEvent('thre')
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions