From 72219ff8d7aa6da9db663ba2a98020960e089200 Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Tue, 5 Feb 2019 00:44:36 +0200 Subject: [PATCH] Modified isMixinConstructorType to allow the rest parameter to the mixin constructor constraint to be either any[] or unknown[] --- src/compiler/checker.ts | 7 +- .../mixinClassesAnnotatedWithUnknownRest.js | 188 ++++++++++++++++ ...xinClassesAnnotatedWithUnknownRest.symbols | 194 +++++++++++++++++ ...mixinClassesAnnotatedWithUnknownRest.types | 206 ++++++++++++++++++ .../mixinClassesAnnotatedWithUnknownRest.ts | 68 ++++++ 5 files changed, 662 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.js create mode 100644 tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.symbols create mode 100644 tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.types create mode 100644 tests/cases/conformance/classes/mixinClassesAnnotatedWithUnknownRest.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d5e4b29d44f1b..a8e875f18c857 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -494,6 +494,7 @@ namespace ts { let globalRegExpType: ObjectType; let globalThisType: GenericType; let anyArrayType: Type; + let unknownArrayType: Type; let autoArrayType: Type; let anyReadonlyArrayType: Type; let deferredGlobalNonNullableTypeAlias: Symbol; @@ -5850,7 +5851,10 @@ namespace ts { const signatures = getSignaturesOfType(type, SignatureKind.Construct); if (signatures.length === 1) { const s = signatures[0]; - return !s.typeParameters && s.parameters.length === 1 && s.hasRestParameter && getTypeOfParameter(s.parameters[0]) === anyArrayType; + if (!s.typeParameters && s.parameters.length === 1 && s.hasRestParameter) { + const restParameterType = getTypeOfParameter(s.parameters[0]); + return restParameterType === anyArrayType || restParameterType === unknownArrayType; + } } return false; } @@ -29835,6 +29839,7 @@ namespace ts { globalBooleanType = getGlobalType("Boolean" as __String, /*arity*/ 0, /*reportErrors*/ true); globalRegExpType = getGlobalType("RegExp" as __String, /*arity*/ 0, /*reportErrors*/ true); anyArrayType = createArrayType(anyType); + unknownArrayType = createArrayType(unknownType); autoArrayType = createArrayType(autoType); if (autoArrayType === emptyObjectType) { diff --git a/tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.js b/tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.js new file mode 100644 index 0000000000000..50519aa735afa --- /dev/null +++ b/tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.js @@ -0,0 +1,188 @@ +//// [mixinClassesAnnotatedWithUnknownRest.ts] +// As per bug #29707 allow mixin constructor to have rest parameter of type unknown[] + +type Constructor = new(...args: unknown[]) => T; + +class Base { + constructor(public x: number, public y: number) {} +} + +class Derived extends Base { + constructor(x: number, y: number, public z: number) { + super(x, y); + } +} + +interface Printable { + print(): void; +} + +const Printable = >(superClass: T): Constructor & { message: string } & T => + class extends superClass { + static message = "hello"; + print() { + const output = this.x + "," + this.y; + } + } + +interface Tagged { + _tag: string; +} + +function Tagged>(superClass: T): Constructor & T { + class C extends superClass { + _tag: string; + constructor(...args: unknown[]) { + super(...args); + this._tag = "hello"; + } + } + return C; +} + +const Thing1 = Tagged(Derived); +const Thing2 = Tagged(Printable(Derived)); +Thing2.message; + +function f1() { + const thing = new Thing1(1, 2, 3); + thing.x; + thing._tag; +} + +function f2() { + const thing = new Thing2(1, 2, 3); + thing.x; + thing._tag; + thing.print(); +} + +class Thing3 extends Thing2 { + constructor(tag: string) { + super(10, 20, 30); + this._tag = tag; + } + test() { + this.print(); + } +} + + +//// [mixinClassesAnnotatedWithUnknownRest.js] +// As per bug #29707 allow mixin constructor to have rest parameter of type unknown[] +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 __()); + }; +})(); +var Base = /** @class */ (function () { + function Base(x, y) { + this.x = x; + this.y = y; + } + return Base; +}()); +var Derived = /** @class */ (function (_super) { + __extends(Derived, _super); + function Derived(x, y, z) { + var _this = _super.call(this, x, y) || this; + _this.z = z; + return _this; + } + return Derived; +}(Base)); +var Printable = function (superClass) { var _a; return _a = /** @class */ (function (_super) { + __extends(class_1, _super); + function class_1() { + return _super !== null && _super.apply(this, arguments) || this; + } + class_1.prototype.print = function () { + var output = this.x + "," + this.y; + }; + return class_1; + }(superClass)), + _a.message = "hello", + _a; }; +function Tagged(superClass) { + var C = /** @class */ (function (_super) { + __extends(C, _super); + function C() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var _this = _super.apply(this, args) || this; + _this._tag = "hello"; + return _this; + } + return C; + }(superClass)); + return C; +} +var Thing1 = Tagged(Derived); +var Thing2 = Tagged(Printable(Derived)); +Thing2.message; +function f1() { + var thing = new Thing1(1, 2, 3); + thing.x; + thing._tag; +} +function f2() { + var thing = new Thing2(1, 2, 3); + thing.x; + thing._tag; + thing.print(); +} +var Thing3 = /** @class */ (function (_super) { + __extends(Thing3, _super); + function Thing3(tag) { + var _this = _super.call(this, 10, 20, 30) || this; + _this._tag = tag; + return _this; + } + Thing3.prototype.test = function () { + this.print(); + }; + return Thing3; +}(Thing2)); + + +//// [mixinClassesAnnotatedWithUnknownRest.d.ts] +declare type Constructor = new (...args: unknown[]) => T; +declare class Base { + x: number; + y: number; + constructor(x: number, y: number); +} +declare class Derived extends Base { + z: number; + constructor(x: number, y: number, z: number); +} +interface Printable { + print(): void; +} +declare const Printable: >(superClass: T) => Constructor & { + message: string; +} & T; +interface Tagged { + _tag: string; +} +declare function Tagged>(superClass: T): Constructor & T; +declare const Thing1: Constructor & typeof Derived; +declare const Thing2: Constructor & Constructor & { + message: string; +} & typeof Derived; +declare function f1(): void; +declare function f2(): void; +declare class Thing3 extends Thing2 { + constructor(tag: string); + test(): void; +} diff --git a/tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.symbols b/tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.symbols new file mode 100644 index 0000000000000..a07d1f726ec5d --- /dev/null +++ b/tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.symbols @@ -0,0 +1,194 @@ +=== tests/cases/conformance/classes/mixinClassesAnnotatedWithUnknownRest.ts === +// As per bug #29707 allow mixin constructor to have rest parameter of type unknown[] + +type Constructor = new(...args: unknown[]) => T; +>Constructor : Symbol(Constructor, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 0, 0)) +>T : Symbol(T, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 2, 17)) +>args : Symbol(args, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 2, 26)) +>T : Symbol(T, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 2, 17)) + +class Base { +>Base : Symbol(Base, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 2, 51)) + + constructor(public x: number, public y: number) {} +>x : Symbol(Base.x, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 5, 16)) +>y : Symbol(Base.y, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 5, 33)) +} + +class Derived extends Base { +>Derived : Symbol(Derived, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 6, 1)) +>Base : Symbol(Base, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 2, 51)) + + constructor(x: number, y: number, public z: number) { +>x : Symbol(x, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 9, 16)) +>y : Symbol(y, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 9, 26)) +>z : Symbol(Derived.z, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 9, 37)) + + super(x, y); +>super : Symbol(Base, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 2, 51)) +>x : Symbol(x, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 9, 16)) +>y : Symbol(y, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 9, 26)) + } +} + +interface Printable { +>Printable : Symbol(Printable, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 12, 1), Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 5)) + + print(): void; +>print : Symbol(Printable.print, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 14, 21)) +} + +const Printable = >(superClass: T): Constructor & { message: string } & T => +>Printable : Symbol(Printable, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 12, 1), Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 5)) +>T : Symbol(T, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 19)) +>Constructor : Symbol(Constructor, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 0, 0)) +>Base : Symbol(Base, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 2, 51)) +>superClass : Symbol(superClass, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 48)) +>T : Symbol(T, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 19)) +>Constructor : Symbol(Constructor, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 0, 0)) +>Printable : Symbol(Printable, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 12, 1), Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 5)) +>message : Symbol(message, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 90)) +>T : Symbol(T, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 19)) + + class extends superClass { +>superClass : Symbol(superClass, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 48)) + + static message = "hello"; +>message : Symbol((Anonymous class).message, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 19, 30)) + + print() { +>print : Symbol((Anonymous class).print, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 20, 33)) + + const output = this.x + "," + this.y; +>output : Symbol(output, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 22, 17)) +>this.x : Symbol(Base.x, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 5, 16)) +>this : Symbol((Anonymous class), Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 115)) +>x : Symbol(Base.x, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 5, 16)) +>this.y : Symbol(Base.y, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 5, 33)) +>this : Symbol((Anonymous class), Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 115)) +>y : Symbol(Base.y, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 5, 33)) + } + } + +interface Tagged { +>Tagged : Symbol(Tagged, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 28, 1), Decl(mixinClassesAnnotatedWithUnknownRest.ts, 24, 5)) + + _tag: string; +>_tag : Symbol(Tagged._tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 26, 18)) +} + +function Tagged>(superClass: T): Constructor & T { +>Tagged : Symbol(Tagged, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 28, 1), Decl(mixinClassesAnnotatedWithUnknownRest.ts, 24, 5)) +>T : Symbol(T, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 30, 16)) +>Constructor : Symbol(Constructor, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 0, 0)) +>superClass : Symbol(superClass, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 30, 43)) +>T : Symbol(T, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 30, 16)) +>Constructor : Symbol(Constructor, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 0, 0)) +>Tagged : Symbol(Tagged, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 28, 1), Decl(mixinClassesAnnotatedWithUnknownRest.ts, 24, 5)) +>T : Symbol(T, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 30, 16)) + + class C extends superClass { +>C : Symbol(C, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 30, 84)) +>superClass : Symbol(superClass, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 30, 43)) + + _tag: string; +>_tag : Symbol(C._tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 31, 32)) + + constructor(...args: unknown[]) { +>args : Symbol(args, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 33, 20)) + + super(...args); +>super : Symbol(T, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 30, 16)) +>args : Symbol(args, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 33, 20)) + + this._tag = "hello"; +>this._tag : Symbol(C._tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 31, 32)) +>this : Symbol(C, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 30, 84)) +>_tag : Symbol(C._tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 31, 32)) + } + } + return C; +>C : Symbol(C, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 30, 84)) +} + +const Thing1 = Tagged(Derived); +>Thing1 : Symbol(Thing1, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 41, 5)) +>Tagged : Symbol(Tagged, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 28, 1), Decl(mixinClassesAnnotatedWithUnknownRest.ts, 24, 5)) +>Derived : Symbol(Derived, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 6, 1)) + +const Thing2 = Tagged(Printable(Derived)); +>Thing2 : Symbol(Thing2, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 42, 5)) +>Tagged : Symbol(Tagged, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 28, 1), Decl(mixinClassesAnnotatedWithUnknownRest.ts, 24, 5)) +>Printable : Symbol(Printable, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 12, 1), Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 5)) +>Derived : Symbol(Derived, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 6, 1)) + +Thing2.message; +>Thing2.message : Symbol(message, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 90)) +>Thing2 : Symbol(Thing2, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 42, 5)) +>message : Symbol(message, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 18, 90)) + +function f1() { +>f1 : Symbol(f1, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 43, 15)) + + const thing = new Thing1(1, 2, 3); +>thing : Symbol(thing, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 46, 9)) +>Thing1 : Symbol(Thing1, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 41, 5)) + + thing.x; +>thing.x : Symbol(Base.x, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 5, 16)) +>thing : Symbol(thing, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 46, 9)) +>x : Symbol(Base.x, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 5, 16)) + + thing._tag; +>thing._tag : Symbol(Tagged._tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 26, 18)) +>thing : Symbol(thing, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 46, 9)) +>_tag : Symbol(Tagged._tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 26, 18)) +} + +function f2() { +>f2 : Symbol(f2, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 49, 1)) + + const thing = new Thing2(1, 2, 3); +>thing : Symbol(thing, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 52, 9)) +>Thing2 : Symbol(Thing2, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 42, 5)) + + thing.x; +>thing.x : Symbol(Base.x, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 5, 16)) +>thing : Symbol(thing, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 52, 9)) +>x : Symbol(Base.x, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 5, 16)) + + thing._tag; +>thing._tag : Symbol(Tagged._tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 26, 18)) +>thing : Symbol(thing, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 52, 9)) +>_tag : Symbol(Tagged._tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 26, 18)) + + thing.print(); +>thing.print : Symbol(Printable.print, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 14, 21)) +>thing : Symbol(thing, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 52, 9)) +>print : Symbol(Printable.print, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 14, 21)) +} + +class Thing3 extends Thing2 { +>Thing3 : Symbol(Thing3, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 56, 1)) +>Thing2 : Symbol(Thing2, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 42, 5)) + + constructor(tag: string) { +>tag : Symbol(tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 59, 16)) + + super(10, 20, 30); + this._tag = tag; +>this._tag : Symbol(Tagged._tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 26, 18)) +>this : Symbol(Thing3, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 56, 1)) +>_tag : Symbol(Tagged._tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 26, 18)) +>tag : Symbol(tag, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 59, 16)) + } + test() { +>test : Symbol(Thing3.test, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 62, 5)) + + this.print(); +>this.print : Symbol(Printable.print, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 14, 21)) +>this : Symbol(Thing3, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 56, 1)) +>print : Symbol(Printable.print, Decl(mixinClassesAnnotatedWithUnknownRest.ts, 14, 21)) + } +} + diff --git a/tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.types b/tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.types new file mode 100644 index 0000000000000..09c5d0d91c5b9 --- /dev/null +++ b/tests/baselines/reference/mixinClassesAnnotatedWithUnknownRest.types @@ -0,0 +1,206 @@ +=== tests/cases/conformance/classes/mixinClassesAnnotatedWithUnknownRest.ts === +// As per bug #29707 allow mixin constructor to have rest parameter of type unknown[] + +type Constructor = new(...args: unknown[]) => T; +>Constructor : Constructor +>args : unknown[] + +class Base { +>Base : Base + + constructor(public x: number, public y: number) {} +>x : number +>y : number +} + +class Derived extends Base { +>Derived : Derived +>Base : Base + + constructor(x: number, y: number, public z: number) { +>x : number +>y : number +>z : number + + super(x, y); +>super(x, y) : void +>super : typeof Base +>x : number +>y : number + } +} + +interface Printable { + print(): void; +>print : () => void +} + +const Printable = >(superClass: T): Constructor & { message: string } & T => +>Printable : >(superClass: T) => Constructor & { message: string; } & T +>>(superClass: T): Constructor & { message: string } & T => class extends superClass { static message = "hello"; print() { const output = this.x + "," + this.y; } } : >(superClass: T) => Constructor & { message: string; } & T +>superClass : T +>message : string + + class extends superClass { +>class extends superClass { static message = "hello"; print() { const output = this.x + "," + this.y; } } : { new (...args: unknown[]): (Anonymous class); prototype: Printable.(Anonymous class); message: string; } & T +>superClass : Base + + static message = "hello"; +>message : string +>"hello" : "hello" + + print() { +>print : () => void + + const output = this.x + "," + this.y; +>output : string +>this.x + "," + this.y : string +>this.x + "," : string +>this.x : number +>this : this +>x : number +>"," : "," +>this.y : number +>this : this +>y : number + } + } + +interface Tagged { + _tag: string; +>_tag : string +} + +function Tagged>(superClass: T): Constructor & T { +>Tagged : >(superClass: T) => Constructor & T +>superClass : T + + class C extends superClass { +>C : C +>superClass : {} + + _tag: string; +>_tag : string + + constructor(...args: unknown[]) { +>args : unknown[] + + super(...args); +>super(...args) : void +>super : T +>...args : unknown +>args : unknown[] + + this._tag = "hello"; +>this._tag = "hello" : "hello" +>this._tag : string +>this : this +>_tag : string +>"hello" : "hello" + } + } + return C; +>C : { new (...args: unknown[]): C; prototype: Tagged.C; } & T +} + +const Thing1 = Tagged(Derived); +>Thing1 : Constructor & typeof Derived +>Tagged(Derived) : Constructor & typeof Derived +>Tagged : >(superClass: T) => Constructor & T +>Derived : typeof Derived + +const Thing2 = Tagged(Printable(Derived)); +>Thing2 : Constructor & Constructor & { message: string; } & typeof Derived +>Tagged(Printable(Derived)) : Constructor & Constructor & { message: string; } & typeof Derived +>Tagged : >(superClass: T) => Constructor & T +>Printable(Derived) : Constructor & { message: string; } & typeof Derived +>Printable : >(superClass: T) => Constructor & { message: string; } & T +>Derived : typeof Derived + +Thing2.message; +>Thing2.message : string +>Thing2 : Constructor & Constructor & { message: string; } & typeof Derived +>message : string + +function f1() { +>f1 : () => void + + const thing = new Thing1(1, 2, 3); +>thing : Tagged & Derived +>new Thing1(1, 2, 3) : Tagged & Derived +>Thing1 : Constructor & typeof Derived +>1 : 1 +>2 : 2 +>3 : 3 + + thing.x; +>thing.x : number +>thing : Tagged & Derived +>x : number + + thing._tag; +>thing._tag : string +>thing : Tagged & Derived +>_tag : string +} + +function f2() { +>f2 : () => void + + const thing = new Thing2(1, 2, 3); +>thing : Tagged & Printable & Derived +>new Thing2(1, 2, 3) : Tagged & Printable & Derived +>Thing2 : Constructor & Constructor & { message: string; } & typeof Derived +>1 : 1 +>2 : 2 +>3 : 3 + + thing.x; +>thing.x : number +>thing : Tagged & Printable & Derived +>x : number + + thing._tag; +>thing._tag : string +>thing : Tagged & Printable & Derived +>_tag : string + + thing.print(); +>thing.print() : void +>thing.print : () => void +>thing : Tagged & Printable & Derived +>print : () => void +} + +class Thing3 extends Thing2 { +>Thing3 : Thing3 +>Thing2 : Tagged & Printable & Derived + + constructor(tag: string) { +>tag : string + + super(10, 20, 30); +>super(10, 20, 30) : void +>super : Constructor & Constructor & { message: string; } & typeof Derived +>10 : 10 +>20 : 20 +>30 : 30 + + this._tag = tag; +>this._tag = tag : string +>this._tag : string +>this : this +>_tag : string +>tag : string + } + test() { +>test : () => void + + this.print(); +>this.print() : void +>this.print : () => void +>this : this +>print : () => void + } +} + diff --git a/tests/cases/conformance/classes/mixinClassesAnnotatedWithUnknownRest.ts b/tests/cases/conformance/classes/mixinClassesAnnotatedWithUnknownRest.ts new file mode 100644 index 0000000000000..fa5d08c7b8b39 --- /dev/null +++ b/tests/cases/conformance/classes/mixinClassesAnnotatedWithUnknownRest.ts @@ -0,0 +1,68 @@ +// As per bug #29707 allow mixin constructor to have rest parameter of type unknown[] +// @declaration: true + +type Constructor = new(...args: unknown[]) => T; + +class Base { + constructor(public x: number, public y: number) {} +} + +class Derived extends Base { + constructor(x: number, y: number, public z: number) { + super(x, y); + } +} + +interface Printable { + print(): void; +} + +const Printable = >(superClass: T): Constructor & { message: string } & T => + class extends superClass { + static message = "hello"; + print() { + const output = this.x + "," + this.y; + } + } + +interface Tagged { + _tag: string; +} + +function Tagged>(superClass: T): Constructor & T { + class C extends superClass { + _tag: string; + constructor(...args: unknown[]) { + super(...args); + this._tag = "hello"; + } + } + return C; +} + +const Thing1 = Tagged(Derived); +const Thing2 = Tagged(Printable(Derived)); +Thing2.message; + +function f1() { + const thing = new Thing1(1, 2, 3); + thing.x; + thing._tag; +} + +function f2() { + const thing = new Thing2(1, 2, 3); + thing.x; + thing._tag; + thing.print(); +} + +class Thing3 extends Thing2 { + constructor(tag: string) { + super(10, 20, 30); + this._tag = tag; + } + test() { + this.print(); + } +}