mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 18:04:18 -05:00
Relax the constraints of isValidBaseType to allow base types to be constructor types (#33146)
* Relax the constraints of isValidBaseType to allow base types to be constructor types * Fix nit * Reduce confusion between isConstructorType and isValidBaseType * Update comment
This commit is contained in:
@@ -5985,7 +5985,9 @@ namespace ts {
|
||||
|
||||
function getBaseTypeVariableOfClass(symbol: Symbol) {
|
||||
const baseConstructorType = getBaseConstructorTypeOfClass(getDeclaredTypeOfClassOrInterface(symbol));
|
||||
return baseConstructorType.flags & TypeFlags.TypeVariable ? baseConstructorType : undefined;
|
||||
return baseConstructorType.flags & TypeFlags.TypeVariable ? baseConstructorType :
|
||||
baseConstructorType.flags & TypeFlags.Intersection ? find((baseConstructorType as IntersectionType).types, t => !!(t.flags & TypeFlags.TypeVariable)) :
|
||||
undefined;
|
||||
}
|
||||
|
||||
function getTypeOfFuncClassEnumModule(symbol: Symbol): Type {
|
||||
@@ -6263,12 +6265,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isConstructorType(type: Type): boolean {
|
||||
if (isValidBaseType(type) && getSignaturesOfType(type, SignatureKind.Construct).length > 0) {
|
||||
if (getSignaturesOfType(type, SignatureKind.Construct).length > 0) {
|
||||
return true;
|
||||
}
|
||||
if (type.flags & TypeFlags.TypeVariable) {
|
||||
const constraint = getBaseConstraintOfType(type);
|
||||
return !!constraint && isValidBaseType(constraint) && isMixinConstructorType(constraint);
|
||||
return !!constraint && isMixinConstructorType(constraint);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -6429,9 +6431,16 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
// A valid base type is `any`, any non-generic object type or intersection of non-generic
|
||||
// object types.
|
||||
// A valid base type is `any`, an object type or intersection of object types.
|
||||
function isValidBaseType(type: Type): type is BaseType {
|
||||
if (type.flags & TypeFlags.TypeParameter) {
|
||||
const constraint = getBaseConstraintOfType(type);
|
||||
if (constraint) {
|
||||
return isValidBaseType(constraint);
|
||||
}
|
||||
}
|
||||
// TODO: Given that we allow type parmeters here now, is this `!isGenericMappedType(type)` check really needed?
|
||||
// There's no reason a `T` should be allowed while a `Readonly<T>` should not.
|
||||
return !!(type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.Any)) && !isGenericMappedType(type) ||
|
||||
!!(type.flags & TypeFlags.Intersection) && every((<IntersectionType>type).types, isValidBaseType);
|
||||
}
|
||||
|
||||
@@ -4202,7 +4202,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Object type or intersection of object types
|
||||
export type BaseType = ObjectType | IntersectionType;
|
||||
export type BaseType = ObjectType | IntersectionType | TypeVariable; // Also `any` and `object`
|
||||
|
||||
export interface InterfaceTypeWithDeclaredMembers extends InterfaceType {
|
||||
declaredProperties: Symbol[]; // Declared members
|
||||
|
||||
@@ -2340,7 +2340,7 @@ declare namespace ts {
|
||||
localTypeParameters: TypeParameter[] | undefined;
|
||||
thisType: TypeParameter | undefined;
|
||||
}
|
||||
export type BaseType = ObjectType | IntersectionType;
|
||||
export type BaseType = ObjectType | IntersectionType | TypeVariable;
|
||||
export interface InterfaceTypeWithDeclaredMembers extends InterfaceType {
|
||||
declaredProperties: Symbol[];
|
||||
declaredCallSignatures: Signature[];
|
||||
|
||||
@@ -2340,7 +2340,7 @@ declare namespace ts {
|
||||
localTypeParameters: TypeParameter[] | undefined;
|
||||
thisType: TypeParameter | undefined;
|
||||
}
|
||||
export type BaseType = ObjectType | IntersectionType;
|
||||
export type BaseType = ObjectType | IntersectionType | TypeVariable;
|
||||
export interface InterfaceTypeWithDeclaredMembers extends InterfaceType {
|
||||
declaredProperties: Symbol[];
|
||||
declaredCallSignatures: Signature[];
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
tests/cases/compiler/baseConstraintOfDecorator.ts(2,5): error TS2322: Type 'typeof decoratorFunc' is not assignable to type 'TFunction'.
|
||||
'typeof decoratorFunc' is assignable to the constraint of type 'TFunction', but 'TFunction' could be instantiated with a different subtype of constraint '{}'.
|
||||
tests/cases/compiler/baseConstraintOfDecorator.ts(2,40): error TS2507: Type 'TFunction' is not a constructor function type.
|
||||
tests/cases/compiler/baseConstraintOfDecorator.ts(12,5): error TS2322: Type 'typeof decoratorFunc' is not assignable to type 'TFunction'.
|
||||
tests/cases/compiler/baseConstraintOfDecorator.ts(12,40): error TS2507: Type 'TFunction' is not a constructor function type.
|
||||
tests/cases/compiler/baseConstraintOfDecorator.ts(12,18): error TS2545: A mixin class must have a constructor with a single rest parameter of type 'any[]'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/baseConstraintOfDecorator.ts (4 errors) ====
|
||||
==== tests/cases/compiler/baseConstraintOfDecorator.ts (3 errors) ====
|
||||
export function classExtender<TFunction>(superClass: TFunction, _instanceModifier: (instance: any, args: any[]) => void): TFunction {
|
||||
return class decoratorFunc extends superClass {
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -29,20 +28,12 @@ tests/cases/compiler/baseConstraintOfDecorator.ts(12,40): error TS2507: Type 'TF
|
||||
class MyClass { private x; }
|
||||
export function classExtender2<TFunction extends new (...args: string[]) => MyClass>(superClass: TFunction, _instanceModifier: (instance: any, args: any[]) => void): TFunction {
|
||||
return class decoratorFunc extends superClass {
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~
|
||||
!!! error TS2507: Type 'TFunction' is not a constructor function type.
|
||||
!!! related TS2735 tests/cases/compiler/baseConstraintOfDecorator.ts:11:32: Did you mean for 'TFunction' to be constrained to type 'new (...args: any[]) => MyClass'?
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2545: A mixin class must have a constructor with a single rest parameter of type 'any[]'.
|
||||
constructor(...args: any[]) {
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
super(...args);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
_instanceModifier(this, args);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
}
|
||||
~~~~~~~~~
|
||||
};
|
||||
~~~~~~
|
||||
!!! error TS2322: Type 'typeof decoratorFunc' is not assignable to type 'TFunction'.
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ export function classExtender2<TFunction extends new (...args: string[]) => MyCl
|
||||
>args : Symbol(args, Decl(baseConstraintOfDecorator.ts, 12, 20))
|
||||
|
||||
super(...args);
|
||||
>super : Symbol(TFunction, Decl(baseConstraintOfDecorator.ts, 10, 31))
|
||||
>args : Symbol(args, Decl(baseConstraintOfDecorator.ts, 12, 20))
|
||||
|
||||
_instanceModifier(this, args);
|
||||
|
||||
@@ -42,16 +42,16 @@ export function classExtender2<TFunction extends new (...args: string[]) => MyCl
|
||||
>args : any[]
|
||||
|
||||
return class decoratorFunc extends superClass {
|
||||
>class decoratorFunc extends superClass { constructor(...args: any[]) { super(...args); _instanceModifier(this, args); } } : typeof decoratorFunc
|
||||
>decoratorFunc : typeof decoratorFunc
|
||||
>superClass : TFunction
|
||||
>class decoratorFunc extends superClass { constructor(...args: any[]) { super(...args); _instanceModifier(this, args); } } : { new (...args: any[]): decoratorFunc; prototype: classExtender2<any>.decoratorFunc; } & TFunction
|
||||
>decoratorFunc : { new (...args: any[]): decoratorFunc; prototype: classExtender2<any>.decoratorFunc; } & TFunction
|
||||
>superClass : MyClass
|
||||
|
||||
constructor(...args: any[]) {
|
||||
>args : any[]
|
||||
|
||||
super(...args);
|
||||
>super(...args) : void
|
||||
>super : any
|
||||
>super : TFunction
|
||||
>...args : any
|
||||
>args : any[]
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
//// [mixinIntersectionIsValidbaseType.ts]
|
||||
export type Constructor<T extends object = object> = new (...args: any[]) => T;
|
||||
|
||||
export interface Initable {
|
||||
init(...args: any[]): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plain mixin where the superclass must be Initable
|
||||
*/
|
||||
export const Serializable = <K extends Constructor<Initable> & Initable>(
|
||||
SuperClass: K
|
||||
) => {
|
||||
const LocalMixin = (InnerSuperClass: K) => {
|
||||
return class SerializableLocal extends InnerSuperClass {
|
||||
}
|
||||
};
|
||||
let ResultClass = LocalMixin(SuperClass);
|
||||
return ResultClass;
|
||||
};
|
||||
|
||||
const AMixin = <K extends Constructor<Initable> & Initable>(SuperClass: K) => {
|
||||
let SomeHowOkay = class A extends SuperClass {
|
||||
};
|
||||
|
||||
let SomeHowNotOkay = class A extends Serializable(SuperClass) {
|
||||
};
|
||||
};
|
||||
|
||||
//// [mixinIntersectionIsValidbaseType.js]
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
exports.__esModule = true;
|
||||
/**
|
||||
* Plain mixin where the superclass must be Initable
|
||||
*/
|
||||
exports.Serializable = function (SuperClass) {
|
||||
var LocalMixin = function (InnerSuperClass) {
|
||||
return /** @class */ (function (_super) {
|
||||
__extends(SerializableLocal, _super);
|
||||
function SerializableLocal() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return SerializableLocal;
|
||||
}(InnerSuperClass));
|
||||
};
|
||||
var ResultClass = LocalMixin(SuperClass);
|
||||
return ResultClass;
|
||||
};
|
||||
var AMixin = function (SuperClass) {
|
||||
var SomeHowOkay = /** @class */ (function (_super) {
|
||||
__extends(A, _super);
|
||||
function A() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return A;
|
||||
}(SuperClass));
|
||||
var SomeHowNotOkay = /** @class */ (function (_super) {
|
||||
__extends(A, _super);
|
||||
function A() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return A;
|
||||
}(exports.Serializable(SuperClass)));
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
=== tests/cases/compiler/mixinIntersectionIsValidbaseType.ts ===
|
||||
export type Constructor<T extends object = object> = new (...args: any[]) => T;
|
||||
>Constructor : Symbol(Constructor, Decl(mixinIntersectionIsValidbaseType.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(mixinIntersectionIsValidbaseType.ts, 0, 24))
|
||||
>args : Symbol(args, Decl(mixinIntersectionIsValidbaseType.ts, 0, 58))
|
||||
>T : Symbol(T, Decl(mixinIntersectionIsValidbaseType.ts, 0, 24))
|
||||
|
||||
export interface Initable {
|
||||
>Initable : Symbol(Initable, Decl(mixinIntersectionIsValidbaseType.ts, 0, 79))
|
||||
|
||||
init(...args: any[]): void;
|
||||
>init : Symbol(Initable.init, Decl(mixinIntersectionIsValidbaseType.ts, 2, 27))
|
||||
>args : Symbol(args, Decl(mixinIntersectionIsValidbaseType.ts, 3, 9))
|
||||
}
|
||||
|
||||
/**
|
||||
* Plain mixin where the superclass must be Initable
|
||||
*/
|
||||
export const Serializable = <K extends Constructor<Initable> & Initable>(
|
||||
>Serializable : Symbol(Serializable, Decl(mixinIntersectionIsValidbaseType.ts, 9, 12))
|
||||
>K : Symbol(K, Decl(mixinIntersectionIsValidbaseType.ts, 9, 29))
|
||||
>Constructor : Symbol(Constructor, Decl(mixinIntersectionIsValidbaseType.ts, 0, 0))
|
||||
>Initable : Symbol(Initable, Decl(mixinIntersectionIsValidbaseType.ts, 0, 79))
|
||||
>Initable : Symbol(Initable, Decl(mixinIntersectionIsValidbaseType.ts, 0, 79))
|
||||
|
||||
SuperClass: K
|
||||
>SuperClass : Symbol(SuperClass, Decl(mixinIntersectionIsValidbaseType.ts, 9, 73))
|
||||
>K : Symbol(K, Decl(mixinIntersectionIsValidbaseType.ts, 9, 29))
|
||||
|
||||
) => {
|
||||
const LocalMixin = (InnerSuperClass: K) => {
|
||||
>LocalMixin : Symbol(LocalMixin, Decl(mixinIntersectionIsValidbaseType.ts, 12, 9))
|
||||
>InnerSuperClass : Symbol(InnerSuperClass, Decl(mixinIntersectionIsValidbaseType.ts, 12, 24))
|
||||
>K : Symbol(K, Decl(mixinIntersectionIsValidbaseType.ts, 9, 29))
|
||||
|
||||
return class SerializableLocal extends InnerSuperClass {
|
||||
>SerializableLocal : Symbol(SerializableLocal, Decl(mixinIntersectionIsValidbaseType.ts, 13, 14))
|
||||
>InnerSuperClass : Symbol(InnerSuperClass, Decl(mixinIntersectionIsValidbaseType.ts, 12, 24))
|
||||
}
|
||||
};
|
||||
let ResultClass = LocalMixin(SuperClass);
|
||||
>ResultClass : Symbol(ResultClass, Decl(mixinIntersectionIsValidbaseType.ts, 16, 7))
|
||||
>LocalMixin : Symbol(LocalMixin, Decl(mixinIntersectionIsValidbaseType.ts, 12, 9))
|
||||
>SuperClass : Symbol(SuperClass, Decl(mixinIntersectionIsValidbaseType.ts, 9, 73))
|
||||
|
||||
return ResultClass;
|
||||
>ResultClass : Symbol(ResultClass, Decl(mixinIntersectionIsValidbaseType.ts, 16, 7))
|
||||
|
||||
};
|
||||
|
||||
const AMixin = <K extends Constructor<Initable> & Initable>(SuperClass: K) => {
|
||||
>AMixin : Symbol(AMixin, Decl(mixinIntersectionIsValidbaseType.ts, 20, 5))
|
||||
>K : Symbol(K, Decl(mixinIntersectionIsValidbaseType.ts, 20, 16))
|
||||
>Constructor : Symbol(Constructor, Decl(mixinIntersectionIsValidbaseType.ts, 0, 0))
|
||||
>Initable : Symbol(Initable, Decl(mixinIntersectionIsValidbaseType.ts, 0, 79))
|
||||
>Initable : Symbol(Initable, Decl(mixinIntersectionIsValidbaseType.ts, 0, 79))
|
||||
>SuperClass : Symbol(SuperClass, Decl(mixinIntersectionIsValidbaseType.ts, 20, 60))
|
||||
>K : Symbol(K, Decl(mixinIntersectionIsValidbaseType.ts, 20, 16))
|
||||
|
||||
let SomeHowOkay = class A extends SuperClass {
|
||||
>SomeHowOkay : Symbol(SomeHowOkay, Decl(mixinIntersectionIsValidbaseType.ts, 21, 7))
|
||||
>A : Symbol(A, Decl(mixinIntersectionIsValidbaseType.ts, 21, 21))
|
||||
>SuperClass : Symbol(SuperClass, Decl(mixinIntersectionIsValidbaseType.ts, 20, 60))
|
||||
|
||||
};
|
||||
|
||||
let SomeHowNotOkay = class A extends Serializable(SuperClass) {
|
||||
>SomeHowNotOkay : Symbol(SomeHowNotOkay, Decl(mixinIntersectionIsValidbaseType.ts, 24, 7))
|
||||
>A : Symbol(A, Decl(mixinIntersectionIsValidbaseType.ts, 24, 24))
|
||||
>Serializable : Symbol(Serializable, Decl(mixinIntersectionIsValidbaseType.ts, 9, 12))
|
||||
>SuperClass : Symbol(SuperClass, Decl(mixinIntersectionIsValidbaseType.ts, 20, 60))
|
||||
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
=== tests/cases/compiler/mixinIntersectionIsValidbaseType.ts ===
|
||||
export type Constructor<T extends object = object> = new (...args: any[]) => T;
|
||||
>Constructor : Constructor<T>
|
||||
>args : any[]
|
||||
|
||||
export interface Initable {
|
||||
init(...args: any[]): void;
|
||||
>init : (...args: any[]) => void
|
||||
>args : any[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Plain mixin where the superclass must be Initable
|
||||
*/
|
||||
export const Serializable = <K extends Constructor<Initable> & Initable>(
|
||||
>Serializable : <K extends Constructor<Initable> & Initable>(SuperClass: K) => { new (...args: any[]): SerializableLocal; prototype: Serializable<any>.SerializableLocal; init(...args: any[]): void; } & K
|
||||
><K extends Constructor<Initable> & Initable>( SuperClass: K) => { const LocalMixin = (InnerSuperClass: K) => { return class SerializableLocal extends InnerSuperClass { } }; let ResultClass = LocalMixin(SuperClass); return ResultClass;} : <K extends Constructor<Initable> & Initable>(SuperClass: K) => { new (...args: any[]): SerializableLocal; prototype: Serializable<any>.SerializableLocal; init(...args: any[]): void; } & K
|
||||
|
||||
SuperClass: K
|
||||
>SuperClass : K
|
||||
|
||||
) => {
|
||||
const LocalMixin = (InnerSuperClass: K) => {
|
||||
>LocalMixin : (InnerSuperClass: K) => { new (...args: any[]): SerializableLocal; prototype: Serializable<any>.SerializableLocal; init(...args: any[]): void; } & K
|
||||
>(InnerSuperClass: K) => { return class SerializableLocal extends InnerSuperClass { } } : (InnerSuperClass: K) => { new (...args: any[]): SerializableLocal; prototype: Serializable<any>.SerializableLocal; init(...args: any[]): void; } & K
|
||||
>InnerSuperClass : K
|
||||
|
||||
return class SerializableLocal extends InnerSuperClass {
|
||||
>class SerializableLocal extends InnerSuperClass { } : { new (...args: any[]): SerializableLocal; prototype: Serializable<any>.SerializableLocal; init(...args: any[]): void; } & K
|
||||
>SerializableLocal : { new (...args: any[]): SerializableLocal; prototype: Serializable<any>.SerializableLocal; init(...args: any[]): void; } & K
|
||||
>InnerSuperClass : Initable
|
||||
}
|
||||
};
|
||||
let ResultClass = LocalMixin(SuperClass);
|
||||
>ResultClass : { new (...args: any[]): SerializableLocal; prototype: Serializable<any>.SerializableLocal; init(...args: any[]): void; } & K
|
||||
>LocalMixin(SuperClass) : { new (...args: any[]): SerializableLocal; prototype: Serializable<any>.SerializableLocal; init(...args: any[]): void; } & K
|
||||
>LocalMixin : (InnerSuperClass: K) => { new (...args: any[]): SerializableLocal; prototype: Serializable<any>.SerializableLocal; init(...args: any[]): void; } & K
|
||||
>SuperClass : K
|
||||
|
||||
return ResultClass;
|
||||
>ResultClass : { new (...args: any[]): SerializableLocal; prototype: Serializable<any>.SerializableLocal; init(...args: any[]): void; } & K
|
||||
|
||||
};
|
||||
|
||||
const AMixin = <K extends Constructor<Initable> & Initable>(SuperClass: K) => {
|
||||
>AMixin : <K extends Constructor<Initable> & Initable>(SuperClass: K) => void
|
||||
><K extends Constructor<Initable> & Initable>(SuperClass: K) => { let SomeHowOkay = class A extends SuperClass { }; let SomeHowNotOkay = class A extends Serializable(SuperClass) { };} : <K extends Constructor<Initable> & Initable>(SuperClass: K) => void
|
||||
>SuperClass : K
|
||||
|
||||
let SomeHowOkay = class A extends SuperClass {
|
||||
>SomeHowOkay : { new (...args: any[]): A; prototype: AMixin<any>.A; init(...args: any[]): void; } & K
|
||||
>class A extends SuperClass { } : { new (...args: any[]): A; prototype: AMixin<any>.A; init(...args: any[]): void; } & K
|
||||
>A : { new (...args: any[]): A; prototype: AMixin<any>.A; init(...args: any[]): void; } & K
|
||||
>SuperClass : Initable
|
||||
|
||||
};
|
||||
|
||||
let SomeHowNotOkay = class A extends Serializable(SuperClass) {
|
||||
>SomeHowNotOkay : { new (...args: any[]): A; prototype: AMixin<any>.A; init: (...args: any[]) => void; } & K
|
||||
>class A extends Serializable(SuperClass) { } : { new (...args: any[]): A; prototype: AMixin<any>.A; init: (...args: any[]) => void; } & K
|
||||
>A : { new (...args: any[]): A; prototype: AMixin<any>.A; init: (...args: any[]) => void; } & K
|
||||
>Serializable(SuperClass) : Serializable<K>.SerializableLocal & Initable
|
||||
>Serializable : <K extends Constructor<Initable> & Initable>(SuperClass: K) => { new (...args: any[]): SerializableLocal; prototype: Serializable<any>.SerializableLocal; init(...args: any[]): void; } & K
|
||||
>SuperClass : K
|
||||
|
||||
};
|
||||
};
|
||||
27
tests/cases/compiler/mixinIntersectionIsValidbaseType.ts
Normal file
27
tests/cases/compiler/mixinIntersectionIsValidbaseType.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
export type Constructor<T extends object = object> = new (...args: any[]) => T;
|
||||
|
||||
export interface Initable {
|
||||
init(...args: any[]): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plain mixin where the superclass must be Initable
|
||||
*/
|
||||
export const Serializable = <K extends Constructor<Initable> & Initable>(
|
||||
SuperClass: K
|
||||
) => {
|
||||
const LocalMixin = (InnerSuperClass: K) => {
|
||||
return class SerializableLocal extends InnerSuperClass {
|
||||
}
|
||||
};
|
||||
let ResultClass = LocalMixin(SuperClass);
|
||||
return ResultClass;
|
||||
};
|
||||
|
||||
const AMixin = <K extends Constructor<Initable> & Initable>(SuperClass: K) => {
|
||||
let SomeHowOkay = class A extends SuperClass {
|
||||
};
|
||||
|
||||
let SomeHowNotOkay = class A extends Serializable(SuperClass) {
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user