TypeScript
TypeScript copied to clipboard
Error when trying to assign a subclass of a base class with generics to `typeof` of that base class
TypeScript Version: 4.1.2
Search Terms: class generic extends typeof 2322
I stumbled upon a type error when trying to assign a subclass of a base class with generics to typeof of that base class.
Code
declare class Base<T extends Record<string, any>> {
a: T;
constructor(a: T);
}
class Sub1 extends Base<{a: boolean}> {}
const error: typeof Base = Sub1;
// Silence error by adding another constructor definition:
declare class BaseWith2Constructors<T extends Record<string, any>> {
a: T;
constructor(a: T);
constructor(a: T);
}
class Sub2 extends BaseWith2Constructors<{a: boolean}> {}
const noerror: typeof BaseWith2Constructors = Sub2;
Expected behavior:
I would expect the first assignment to not error as well.
Actual behavior:
I get error 2322. The error says Type 'T' is not assignable to type '{ a: boolean; }' and Property 'a' is missing in type 'Record<string, any>' but required in type '{ a: boolean; }' which sounds like the assignment checks are flipped.
Strangely enough, the error can be silenced by adding a second constructor definition. Is that a workaround I can rely on?
If this is expected behavior, how am I supposed to use the base class as common base in this example? I cannot do typeof Base<any> in this case because that's a syntax error.
Playground Link:
https://www.typescriptlang.org/play?ts=4.1.2#code/CYUwxgNghgTiAEkoGdnwEIpAHgCrxAA8AXEAO2DQCVwB7GYbZYmASzIHMAaeKMgTwB8g+AG8AsACh4vAFzxcAbilSZYWmWYwArmGL0AFFHm4AlMskBfFZKSp4AZW0AjAIwES5ShizZRx+GdaWggQPksRUWtJKXVNYgIYGHp5Yn4ABxBaADMfZAQAXkcXVwspAHpyx1ZQsjAEECT6QP5eYGB2Dl4yWmIAC0bEDS1dfRh4UGz2VmJWDVkpUCQ4RGh7THyAdRm+gCYAYWGWUfpkPA9SCmo6BiYWTp4+IUjVOQUy6SH4nT1DALMLGojj8xkYTOYpNFYms0E5nLsLl40BsQNt+gdgScYGd-PIgiEwmQImIobYjvAeo1kjBUhksrkUWi9odvli0EU4btFEA
Related Issues:
These should both be errors -- new error({ a: "" }) is a legal invocation that puts a string where a boolean is expected.
Thanks for the quick reply, that makes sense. Is there a better way then to achieve what I want other than
class Genericbase extends Base<any> {}
const foo: typeof Genericbase = Sub
There are other ways to do it, but that's probably the best one.
:wave: Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of the repro in the issue body running against the nightly TypeScript.
Issue body code block by @dummdidumm
:x: Failed: -
Type 'typeof Sub1' is not assignable to type 'typeof Base'. Types of construct signatures are incompatible. Type 'new (a: { a: boolean; }) => Sub1' is not assignable to type 'new>(a: T) => Base '. Types of parameters 'a' and 'a' are incompatible. Type 'T' is not assignable to type '{ a: boolean; }'. Property 'a' is missing in type 'Record ' but required in type '{ a: boolean; }'.
Historical Information
| Version | Reproduction Outputs |
|---|---|
| 4.2.2, 4.3.2, 4.4.2, 4.5.2, 4.6.2 |
:x: Failed: -
|