Keep accessors as accessors in emitted anonymous class declarations (#60853)

This commit is contained in:
Mateusz Burzyński
2025-06-30 22:19:53 +02:00
committed by GitHub
parent 3267e426e3
commit c35b14335a
32 changed files with 1480 additions and 45 deletions

View File

@@ -467,6 +467,7 @@ import {
IntroducesNewScopeNode,
isAccessExpression,
isAccessor,
isAccessorModifier,
isAliasableExpression,
isAmbientModule,
isArray,
@@ -7690,27 +7691,51 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (propertySymbol.flags & SymbolFlags.Accessor) {
const writeType = getWriteTypeOfSymbol(propertySymbol);
if (propertyType !== writeType && !isErrorType(propertyType) && !isErrorType(writeType)) {
if (!isErrorType(propertyType) && !isErrorType(writeType)) {
const symbolMapper = getSymbolLinks(propertySymbol).mapper;
const getterDeclaration = getDeclarationOfKind<GetAccessorDeclaration>(propertySymbol, SyntaxKind.GetAccessor)!;
const getterSignature = getSignatureFromDeclaration(getterDeclaration);
typeElements.push(
setCommentRange(
context,
signatureToSignatureDeclarationHelper(symbolMapper ? instantiateSignature(getterSignature, symbolMapper) : getterSignature, SyntaxKind.GetAccessor, context, { name: propertyName }) as GetAccessorDeclaration,
getterDeclaration,
),
);
const setterDeclaration = getDeclarationOfKind<SetAccessorDeclaration>(propertySymbol, SyntaxKind.SetAccessor)!;
const setterSignature = getSignatureFromDeclaration(setterDeclaration);
typeElements.push(
setCommentRange(
context,
signatureToSignatureDeclarationHelper(symbolMapper ? instantiateSignature(setterSignature, symbolMapper) : setterSignature, SyntaxKind.SetAccessor, context, { name: propertyName }) as SetAccessorDeclaration,
setterDeclaration,
),
);
return;
const propDeclaration = getDeclarationOfKind<PropertyDeclaration>(propertySymbol, SyntaxKind.PropertyDeclaration);
if (propertyType !== writeType || propertySymbol.parent!.flags & SymbolFlags.Class && !propDeclaration) {
const getterDeclaration = getDeclarationOfKind<GetAccessorDeclaration>(propertySymbol, SyntaxKind.GetAccessor);
if (getterDeclaration) {
const getterSignature = getSignatureFromDeclaration(getterDeclaration);
typeElements.push(
setCommentRange(
context,
signatureToSignatureDeclarationHelper(symbolMapper ? instantiateSignature(getterSignature, symbolMapper) : getterSignature, SyntaxKind.GetAccessor, context, { name: propertyName }) as GetAccessorDeclaration,
getterDeclaration,
),
);
}
const setterDeclaration = getDeclarationOfKind<SetAccessorDeclaration>(propertySymbol, SyntaxKind.SetAccessor);
if (setterDeclaration) {
const setterSignature = getSignatureFromDeclaration(setterDeclaration);
typeElements.push(
setCommentRange(
context,
signatureToSignatureDeclarationHelper(symbolMapper ? instantiateSignature(setterSignature, symbolMapper) : setterSignature, SyntaxKind.SetAccessor, context, { name: propertyName }) as SetAccessorDeclaration,
setterDeclaration,
),
);
}
return;
}
if (propertySymbol.parent!.flags & SymbolFlags.Class && propDeclaration && find(propDeclaration.modifiers, isAccessorModifier)) {
const fakeGetterSignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, emptyArray, propertyType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
typeElements.push(
setCommentRange(
context,
signatureToSignatureDeclarationHelper(fakeGetterSignature, SyntaxKind.GetAccessor, context, { name: propertyName }) as GetAccessorDeclaration,
propDeclaration,
),
);
const setterParam = createSymbol(SymbolFlags.FunctionScopedVariable, "arg" as __String);
setterParam.links.type = writeType;
const fakeSetterSignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, [setterParam], voidType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
typeElements.push(
signatureToSignatureDeclarationHelper(fakeSetterSignature, SyntaxKind.SetAccessor, context, { name: propertyName }) as SetAccessorDeclaration,
);
return;
}
}
}
@@ -12816,13 +12841,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
*/
function getWriteTypeOfSymbol(symbol: Symbol): Type {
const checkFlags = getCheckFlags(symbol);
if (checkFlags & CheckFlags.SyntheticProperty) {
return checkFlags & CheckFlags.DeferredType ?
getWriteTypeOfSymbolWithDeferredType(symbol) || getTypeOfSymbolWithDeferredType(symbol) :
// NOTE: cast to TransientSymbol should be safe because only TransientSymbols can have CheckFlags.SyntheticProperty
(symbol as TransientSymbol).links.writeType || (symbol as TransientSymbol).links.type!;
}
if (symbol.flags & SymbolFlags.Property) {
return checkFlags & CheckFlags.SyntheticProperty ?
checkFlags & CheckFlags.DeferredType ?
getWriteTypeOfSymbolWithDeferredType(symbol) || getTypeOfSymbolWithDeferredType(symbol) :
// NOTE: cast to TransientSymbol should be safe because only TransientSymbols can have CheckFlags.SyntheticProperty
(symbol as TransientSymbol).links.writeType || (symbol as TransientSymbol).links.type! :
removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & SymbolFlags.Optional));
return removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & SymbolFlags.Optional));
}
if (symbol.flags & SymbolFlags.Accessor) {
return checkFlags & CheckFlags.Instantiated ?
@@ -15439,6 +15465,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined {
let propFlags = SymbolFlags.None;
let singleProp: Symbol | undefined;
let propSet: Map<SymbolId, Symbol> | undefined;
let indexTypes: Type[] | undefined;
@@ -15465,6 +15492,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
if (!singleProp) {
singleProp = prop;
propFlags = (prop.flags & SymbolFlags.Accessor) || SymbolFlags.Property;
}
else if (prop !== singleProp) {
const isInstantiation = (getTargetSymbol(prop) || prop) === (getTargetSymbol(singleProp) || singleProp);
@@ -15487,6 +15515,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
propSet.set(id, prop);
}
}
// classes created by mixins are represented as intersections
// and overriding a property in a derived class redefines it completely at runtime
// so a get accessor can't be merged with a set accessor in a base class,
// for that reason the accessor flags are only used when they are the same in all constituents
if (propFlags & SymbolFlags.Accessor && (prop.flags & SymbolFlags.Accessor) !== (propFlags & SymbolFlags.Accessor)) {
propFlags = (propFlags & ~SymbolFlags.Accessor) | SymbolFlags.Property;
}
}
if (isUnion && isReadonlySymbol(prop)) {
checkFlags |= CheckFlags.Readonly;
@@ -15505,6 +15540,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
else if (isUnion) {
const indexInfo = !isLateBoundName(name) && getApplicableIndexInfoForName(type, name);
if (indexInfo) {
propFlags = (propFlags & ~SymbolFlags.Accessor) | SymbolFlags.Property;
checkFlags |= CheckFlags.WritePartial | (indexInfo.isReadonly ? CheckFlags.Readonly : 0);
indexTypes = append(indexTypes, isTupleType(type) ? getRestTypeOfTupleType(type) || undefinedType : indexInfo.type);
}
@@ -15583,7 +15619,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
propTypes.push(type);
}
addRange(propTypes, indexTypes);
const result = createSymbol(SymbolFlags.Property | (optionalFlag ?? 0), name, syntheticFlag | checkFlags);
const result = createSymbol(propFlags | (optionalFlag ?? 0), name, syntheticFlag | checkFlags);
result.links.containingType = containingType;
if (!hasNonUniformValueDeclaration && firstValueDeclaration) {
result.valueDeclaration = firstValueDeclaration;

View File

@@ -0,0 +1,66 @@
//// [tests/cases/conformance/declarationEmit/anonymousClassAccessorsDeclarationEmit1.ts] ////
//// [anonymousClassAccessorsDeclarationEmit1.ts]
export abstract class Base {
accessor a = 1;
}
export function middle(Super = Base) {
abstract class Middle extends Super {}
return Middle;
}
class A {
constructor(...args: any[]) {}
}
export function Mixin<T extends typeof A>(Super: T) {
return class B extends Super {
get myName(): string {
return "B";
}
set myName(arg: string) {}
};
}
//// [anonymousClassAccessorsDeclarationEmit1.js]
export class Base {
accessor a = 1;
}
export function middle(Super = Base) {
class Middle extends Super {
}
return Middle;
}
class A {
constructor(...args) { }
}
export function Mixin(Super) {
return class B extends Super {
get myName() {
return "B";
}
set myName(arg) { }
};
}
//// [anonymousClassAccessorsDeclarationEmit1.d.ts]
export declare abstract class Base {
accessor a: number;
}
export declare function middle(Super?: typeof Base): abstract new () => {
get a(): number;
set a(arg: number);
};
declare class A {
constructor(...args: any[]);
}
export declare function Mixin<T extends typeof A>(Super: T): {
new (...args: any[]): {
get myName(): string;
set myName(arg: string);
};
} & T;
export {};

View File

@@ -0,0 +1,53 @@
//// [tests/cases/conformance/declarationEmit/anonymousClassAccessorsDeclarationEmit1.ts] ////
=== anonymousClassAccessorsDeclarationEmit1.ts ===
export abstract class Base {
>Base : Symbol(Base, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 0, 0))
accessor a = 1;
>a : Symbol(Base.a, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 0, 28))
}
export function middle(Super = Base) {
>middle : Symbol(middle, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 2, 1))
>Super : Symbol(Super, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 4, 23))
>Base : Symbol(Base, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 0, 0))
abstract class Middle extends Super {}
>Middle : Symbol(Middle, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 4, 38))
>Super : Symbol(Super, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 4, 23))
return Middle;
>Middle : Symbol(Middle, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 4, 38))
}
class A {
>A : Symbol(A, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 7, 1))
constructor(...args: any[]) {}
>args : Symbol(args, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 10, 14))
}
export function Mixin<T extends typeof A>(Super: T) {
>Mixin : Symbol(Mixin, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 11, 1))
>T : Symbol(T, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 13, 22))
>A : Symbol(A, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 7, 1))
>Super : Symbol(Super, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 13, 42))
>T : Symbol(T, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 13, 22))
return class B extends Super {
>B : Symbol(B, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 14, 8))
>Super : Symbol(Super, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 13, 42))
get myName(): string {
>myName : Symbol(B.myName, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 14, 32), Decl(anonymousClassAccessorsDeclarationEmit1.ts, 17, 5))
return "B";
}
set myName(arg: string) {}
>myName : Symbol(B.myName, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 14, 32), Decl(anonymousClassAccessorsDeclarationEmit1.ts, 17, 5))
>arg : Symbol(arg, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 18, 15))
};
}

View File

@@ -0,0 +1,75 @@
//// [tests/cases/conformance/declarationEmit/anonymousClassAccessorsDeclarationEmit1.ts] ////
=== anonymousClassAccessorsDeclarationEmit1.ts ===
export abstract class Base {
>Base : Base
> : ^^^^
accessor a = 1;
>a : number
> : ^^^^^^
>1 : 1
> : ^
}
export function middle(Super = Base) {
>middle : (Super?: typeof Base) => typeof Middle
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>Super : typeof Base
> : ^^^^^^^^^^^
>Base : typeof Base
> : ^^^^^^^^^^^
abstract class Middle extends Super {}
>Middle : Middle
> : ^^^^^^
>Super : Base
> : ^^^^
return Middle;
>Middle : typeof Middle
> : ^^^^^^^^^^^^^
}
class A {
>A : A
> : ^
constructor(...args: any[]) {}
>args : any[]
> : ^^^^^
}
export function Mixin<T extends typeof A>(Super: T) {
>Mixin : <T extends typeof A>(Super: T) => { new (...args: any[]): B; prototype: Mixin<any>.B; } & T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>A : typeof A
> : ^^^^^^^^
>Super : T
> : ^
return class B extends Super {
>class B extends Super { get myName(): string { return "B"; } set myName(arg: string) {} } : { new (...args: any[]): B; prototype: Mixin<any>.B; } & T
> : ^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>B : { new (...args: any[]): B; prototype: Mixin<any>.B; } & T
> : ^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>Super : A
> : ^
get myName(): string {
>myName : string
> : ^^^^^^
return "B";
>"B" : "B"
> : ^^^
}
set myName(arg: string) {}
>myName : string
> : ^^^^^^
>arg : string
> : ^^^^^^
};
}

View File

@@ -45,7 +45,9 @@ declare class C2 {
}
declare function f(): {
new (): {
a: any;
get a(): any;
set a(arg: any);
};
b: any;
get b(): any;
set b(arg: any);
};

View File

@@ -0,0 +1,48 @@
//// [tests/cases/compiler/declarationEmitGenericTypeParamerSerialization3.ts] ////
//// [declarationEmitGenericTypeParamerSerialization3.ts]
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
return class extends superclass {};
}
export function wrapper<T>(value: T) {
class BaseClass {
accessor name = value;
}
return class MyClass extends mixin(BaseClass) {
accessor name = value;
}
}
export const Cls = wrapper("test");
//// [declarationEmitGenericTypeParamerSerialization3.js]
function mixin(superclass) {
return class extends superclass {
};
}
export function wrapper(value) {
class BaseClass {
accessor name = value;
}
return class MyClass extends mixin(BaseClass) {
accessor name = value;
};
}
export const Cls = wrapper("test");
//// [declarationEmitGenericTypeParamerSerialization3.d.ts]
export declare function wrapper<T>(value: T): {
new (): {
get name(): T;
set name(arg: T);
};
};
export declare const Cls: {
new (): {
get name(): string;
set name(arg: string);
};
};

View File

@@ -0,0 +1,42 @@
//// [tests/cases/compiler/declarationEmitGenericTypeParamerSerialization3.ts] ////
=== declarationEmitGenericTypeParamerSerialization3.ts ===
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
>mixin : Symbol(mixin, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 0, 0))
>T : Symbol(T, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 0, 15))
>args : Symbol(args, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 0, 32))
>superclass : Symbol(superclass, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 0, 55))
>T : Symbol(T, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 0, 15))
return class extends superclass {};
>superclass : Symbol(superclass, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 0, 55))
}
export function wrapper<T>(value: T) {
>wrapper : Symbol(wrapper, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 2, 1))
>T : Symbol(T, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 4, 24))
>value : Symbol(value, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 4, 27))
>T : Symbol(T, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 4, 24))
class BaseClass {
>BaseClass : Symbol(BaseClass, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 4, 38))
accessor name = value;
>name : Symbol(BaseClass.name, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 5, 19))
>value : Symbol(value, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 4, 27))
}
return class MyClass extends mixin(BaseClass) {
>MyClass : Symbol(MyClass, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 8, 8))
>mixin : Symbol(mixin, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 0, 0))
>BaseClass : Symbol(BaseClass, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 4, 38))
accessor name = value;
>name : Symbol(MyClass.name, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 8, 49))
>value : Symbol(value, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 4, 27))
}
}
export const Cls = wrapper("test");
>Cls : Symbol(Cls, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 13, 12))
>wrapper : Symbol(wrapper, Decl(declarationEmitGenericTypeParamerSerialization3.ts, 2, 1))

View File

@@ -0,0 +1,64 @@
//// [tests/cases/compiler/declarationEmitGenericTypeParamerSerialization3.ts] ////
=== declarationEmitGenericTypeParamerSerialization3.ts ===
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
>mixin : <T extends { new (...args: any[]): {}; }>(superclass: T) => { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>args : any[]
> : ^^^^^
>superclass : T
> : ^
return class extends superclass {};
>class extends superclass {} : { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T
> : ^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>superclass : {}
> : ^^
}
export function wrapper<T>(value: T) {
>wrapper : <T>(value: T) => typeof MyClass
> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^
>value : T
> : ^
class BaseClass {
>BaseClass : BaseClass
> : ^^^^^^^^^
accessor name = value;
>name : T
> : ^
>value : T
> : ^
}
return class MyClass extends mixin(BaseClass) {
>class MyClass extends mixin(BaseClass) { accessor name = value; } : typeof MyClass
> : ^^^^^^^^^^^^^^
>MyClass : typeof MyClass
> : ^^^^^^^^^^^^^^
>mixin(BaseClass) : mixin<typeof BaseClass>.(Anonymous class) & BaseClass
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>mixin : <T_1 extends { new (...args: any[]): {}; }>(superclass: T_1) => { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T_1
> : ^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>BaseClass : typeof BaseClass
> : ^^^^^^^^^^^^^^^^
accessor name = value;
>name : T
> : ^
>value : T
> : ^
}
}
export const Cls = wrapper("test");
>Cls : typeof MyClass
> : ^^^^^^^^^^^^^^
>wrapper("test") : typeof MyClass
> : ^^^^^^^^^^^^^^
>wrapper : <T>(value: T) => typeof MyClass
> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^
>"test" : "test"
> : ^^^^^^

View File

@@ -291,16 +291,16 @@ export function Point2D(x, y) {
}
Point2D.prototype = {
>Point2D.prototype = { __proto__: Vec, get x() { return this.storage[0]; }, /** * @param {number} x */ set x(x) { this.storage[0] = x; }, get y() { return this.storage[1]; }, /** * @param {number} y */ set y(y) { this.storage[1] = y; }} : { __proto__: typeof Vec; x: number; y: number; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
>Point2D.prototype : { __proto__: typeof Vec; x: number; y: number; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
>Point2D.prototype = { __proto__: Vec, get x() { return this.storage[0]; }, /** * @param {number} x */ set x(x) { this.storage[0] = x; }, get y() { return this.storage[1]; }, /** * @param {number} y */ set y(y) { this.storage[1] = y; }} : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
>Point2D.prototype : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
>Point2D : typeof Point2D
> : ^^^^^^^^^^^^^^
>prototype : { __proto__: typeof Vec; x: number; y: number; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
>{ __proto__: Vec, get x() { return this.storage[0]; }, /** * @param {number} x */ set x(x) { this.storage[0] = x; }, get y() { return this.storage[1]; }, /** * @param {number} y */ set y(y) { this.storage[1] = y; }} : { __proto__: typeof Vec; x: number; y: number; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
>prototype : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
>{ __proto__: Vec, get x() { return this.storage[0]; }, /** * @param {number} x */ set x(x) { this.storage[0] = x; }, get y() { return this.storage[1]; }, /** * @param {number} y */ set y(y) { this.storage[1] = y; }} : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
__proto__: Vec,
>__proto__ : typeof Vec
@@ -315,8 +315,8 @@ Point2D.prototype = {
return this.storage[0];
>this.storage[0] : any
>this.storage : any
>this : { __proto__: typeof Vec; x: number; y: number; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
>this : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
>storage : any
> : ^^^
>0 : 0
@@ -337,8 +337,8 @@ Point2D.prototype = {
> : ^^^^^^
>this.storage[0] : any
>this.storage : any
>this : { __proto__: typeof Vec; x: number; y: number; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
>this : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
>storage : any
> : ^^^
>0 : 0
@@ -354,8 +354,8 @@ Point2D.prototype = {
return this.storage[1];
>this.storage[1] : any
>this.storage : any
>this : { __proto__: typeof Vec; x: number; y: number; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
>this : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
>storage : any
> : ^^^
>1 : 1
@@ -376,8 +376,8 @@ Point2D.prototype = {
> : ^^^^^^
>this.storage[1] : any
>this.storage : any
>this : { __proto__: typeof Vec; x: number; y: number; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
>this : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
>storage : any
> : ^^^
>1 : 1

View File

@@ -0,0 +1,66 @@
//// [tests/cases/conformance/classes/mixinAccessors1.ts] ////
//// [mixinAccessors1.ts]
// https://github.com/microsoft/TypeScript/issues/58790
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
return class extends superclass {
get validationTarget(): HTMLElement {
return document.createElement("input");
}
};
}
class BaseClass {
get validationTarget(): HTMLElement {
return document.createElement("div");
}
}
class MyClass extends mixin(BaseClass) {
get validationTarget(): HTMLElement {
return document.createElement("select");
}
}
//// [mixinAccessors1.js]
"use strict";
// https://github.com/microsoft/TypeScript/issues/58790
function mixin(superclass) {
return class extends superclass {
get validationTarget() {
return document.createElement("input");
}
};
}
class BaseClass {
get validationTarget() {
return document.createElement("div");
}
}
class MyClass extends mixin(BaseClass) {
get validationTarget() {
return document.createElement("select");
}
}
//// [mixinAccessors1.d.ts]
declare function mixin<T extends {
new (...args: any[]): {};
}>(superclass: T): {
new (...args: any[]): {
get validationTarget(): HTMLElement;
};
} & T;
declare class BaseClass {
get validationTarget(): HTMLElement;
}
declare const MyClass_base: {
new (...args: any[]): {
get validationTarget(): HTMLElement;
};
} & typeof BaseClass;
declare class MyClass extends MyClass_base {
get validationTarget(): HTMLElement;
}

View File

@@ -0,0 +1,56 @@
//// [tests/cases/conformance/classes/mixinAccessors1.ts] ////
=== mixinAccessors1.ts ===
// https://github.com/microsoft/TypeScript/issues/58790
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
>mixin : Symbol(mixin, Decl(mixinAccessors1.ts, 0, 0))
>T : Symbol(T, Decl(mixinAccessors1.ts, 2, 15))
>args : Symbol(args, Decl(mixinAccessors1.ts, 2, 32))
>superclass : Symbol(superclass, Decl(mixinAccessors1.ts, 2, 55))
>T : Symbol(T, Decl(mixinAccessors1.ts, 2, 15))
return class extends superclass {
>superclass : Symbol(superclass, Decl(mixinAccessors1.ts, 2, 55))
get validationTarget(): HTMLElement {
>validationTarget : Symbol((Anonymous class).validationTarget, Decl(mixinAccessors1.ts, 3, 35))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
return document.createElement("input");
>document.createElement : Symbol(Document.createElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>document : Symbol(document, Decl(lib.dom.d.ts, --, --))
>createElement : Symbol(Document.createElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
}
};
}
class BaseClass {
>BaseClass : Symbol(BaseClass, Decl(mixinAccessors1.ts, 8, 1))
get validationTarget(): HTMLElement {
>validationTarget : Symbol(BaseClass.validationTarget, Decl(mixinAccessors1.ts, 10, 17))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
return document.createElement("div");
>document.createElement : Symbol(Document.createElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>document : Symbol(document, Decl(lib.dom.d.ts, --, --))
>createElement : Symbol(Document.createElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
}
}
class MyClass extends mixin(BaseClass) {
>MyClass : Symbol(MyClass, Decl(mixinAccessors1.ts, 14, 1))
>mixin : Symbol(mixin, Decl(mixinAccessors1.ts, 0, 0))
>BaseClass : Symbol(BaseClass, Decl(mixinAccessors1.ts, 8, 1))
get validationTarget(): HTMLElement {
>validationTarget : Symbol(MyClass.validationTarget, Decl(mixinAccessors1.ts, 16, 40))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
return document.createElement("select");
>document.createElement : Symbol(Document.createElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>document : Symbol(document, Decl(lib.dom.d.ts, --, --))
>createElement : Symbol(Document.createElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
}
}

View File

@@ -0,0 +1,87 @@
//// [tests/cases/conformance/classes/mixinAccessors1.ts] ////
=== mixinAccessors1.ts ===
// https://github.com/microsoft/TypeScript/issues/58790
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
>mixin : <T extends { new (...args: any[]): {}; }>(superclass: T) => { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>args : any[]
> : ^^^^^
>superclass : T
> : ^
return class extends superclass {
>class extends superclass { get validationTarget(): HTMLElement { return document.createElement("input"); } } : { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T
> : ^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>superclass : {}
> : ^^
get validationTarget(): HTMLElement {
>validationTarget : HTMLElement
> : ^^^^^^^^^^^
return document.createElement("input");
>document.createElement("input") : HTMLInputElement
> : ^^^^^^^^^^^^^^^^
>document.createElement : { <K extends keyof HTMLElementTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; <K extends keyof HTMLElementDeprecatedTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; }
> : ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^^
>document : Document
> : ^^^^^^^^
>createElement : { <K extends keyof HTMLElementTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; <K extends keyof HTMLElementDeprecatedTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; }
> : ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^^
>"input" : "input"
> : ^^^^^^^
}
};
}
class BaseClass {
>BaseClass : BaseClass
> : ^^^^^^^^^
get validationTarget(): HTMLElement {
>validationTarget : HTMLElement
> : ^^^^^^^^^^^
return document.createElement("div");
>document.createElement("div") : HTMLDivElement
> : ^^^^^^^^^^^^^^
>document.createElement : { <K extends keyof HTMLElementTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; <K extends keyof HTMLElementDeprecatedTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; }
> : ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^^
>document : Document
> : ^^^^^^^^
>createElement : { <K extends keyof HTMLElementTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; <K extends keyof HTMLElementDeprecatedTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; }
> : ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^^
>"div" : "div"
> : ^^^^^
}
}
class MyClass extends mixin(BaseClass) {
>MyClass : MyClass
> : ^^^^^^^
>mixin(BaseClass) : mixin<typeof BaseClass>.(Anonymous class) & BaseClass
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>mixin : <T extends { new (...args: any[]): {}; }>(superclass: T) => { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>BaseClass : typeof BaseClass
> : ^^^^^^^^^^^^^^^^
get validationTarget(): HTMLElement {
>validationTarget : HTMLElement
> : ^^^^^^^^^^^
return document.createElement("select");
>document.createElement("select") : HTMLSelectElement
> : ^^^^^^^^^^^^^^^^^
>document.createElement : { <K extends keyof HTMLElementTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; <K extends keyof HTMLElementDeprecatedTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; }
> : ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^^
>document : Document
> : ^^^^^^^^
>createElement : { <K extends keyof HTMLElementTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; <K extends keyof HTMLElementDeprecatedTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; }
> : ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^^
>"select" : "select"
> : ^^^^^^^^
}
}

View File

@@ -0,0 +1,54 @@
//// [tests/cases/conformance/classes/mixinAccessors2.ts] ////
//// [mixinAccessors2.ts]
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
return class extends superclass {
accessor name = "";
};
}
class BaseClass {
accessor name = "";
}
class MyClass extends mixin(BaseClass) {
accessor name = "";
}
//// [mixinAccessors2.js]
"use strict";
function mixin(superclass) {
return class extends superclass {
accessor name = "";
};
}
class BaseClass {
accessor name = "";
}
class MyClass extends mixin(BaseClass) {
accessor name = "";
}
//// [mixinAccessors2.d.ts]
declare function mixin<T extends {
new (...args: any[]): {};
}>(superclass: T): {
new (...args: any[]): {
get name(): string;
set name(arg: string);
};
} & T;
declare class BaseClass {
accessor name: string;
}
declare const MyClass_base: {
new (...args: any[]): {
get name(): string;
set name(arg: string);
};
} & typeof BaseClass;
declare class MyClass extends MyClass_base {
accessor name: string;
}

View File

@@ -0,0 +1,35 @@
//// [tests/cases/conformance/classes/mixinAccessors2.ts] ////
=== mixinAccessors2.ts ===
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
>mixin : Symbol(mixin, Decl(mixinAccessors2.ts, 0, 0))
>T : Symbol(T, Decl(mixinAccessors2.ts, 0, 15))
>args : Symbol(args, Decl(mixinAccessors2.ts, 0, 32))
>superclass : Symbol(superclass, Decl(mixinAccessors2.ts, 0, 55))
>T : Symbol(T, Decl(mixinAccessors2.ts, 0, 15))
return class extends superclass {
>superclass : Symbol(superclass, Decl(mixinAccessors2.ts, 0, 55))
accessor name = "";
>name : Symbol((Anonymous class).name, Decl(mixinAccessors2.ts, 1, 35))
};
}
class BaseClass {
>BaseClass : Symbol(BaseClass, Decl(mixinAccessors2.ts, 4, 1))
accessor name = "";
>name : Symbol(BaseClass.name, Decl(mixinAccessors2.ts, 6, 17))
}
class MyClass extends mixin(BaseClass) {
>MyClass : Symbol(MyClass, Decl(mixinAccessors2.ts, 8, 1))
>mixin : Symbol(mixin, Decl(mixinAccessors2.ts, 0, 0))
>BaseClass : Symbol(BaseClass, Decl(mixinAccessors2.ts, 4, 1))
accessor name = "";
>name : Symbol(MyClass.name, Decl(mixinAccessors2.ts, 10, 40))
}

View File

@@ -0,0 +1,54 @@
//// [tests/cases/conformance/classes/mixinAccessors2.ts] ////
=== mixinAccessors2.ts ===
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
>mixin : <T extends { new (...args: any[]): {}; }>(superclass: T) => { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>args : any[]
> : ^^^^^
>superclass : T
> : ^
return class extends superclass {
>class extends superclass { accessor name = ""; } : { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T
> : ^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>superclass : {}
> : ^^
accessor name = "";
>name : string
> : ^^^^^^
>"" : ""
> : ^^
};
}
class BaseClass {
>BaseClass : BaseClass
> : ^^^^^^^^^
accessor name = "";
>name : string
> : ^^^^^^
>"" : ""
> : ^^
}
class MyClass extends mixin(BaseClass) {
>MyClass : MyClass
> : ^^^^^^^
>mixin(BaseClass) : mixin<typeof BaseClass>.(Anonymous class) & BaseClass
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>mixin : <T extends { new (...args: any[]): {}; }>(superclass: T) => { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>BaseClass : typeof BaseClass
> : ^^^^^^^^^^^^^^^^
accessor name = "";
>name : string
> : ^^^^^^
>"" : ""
> : ^^
}

View File

@@ -0,0 +1,25 @@
mixinAccessors3.ts(15,7): error TS2611: 'name' is defined as a property in class 'mixin<typeof BaseClass>.(Anonymous class) & BaseClass', but is overridden here in 'MyClass' as an accessor.
==== mixinAccessors3.ts (1 errors) ====
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
return class extends superclass {
get name() {
return "";
}
};
}
class BaseClass {
set name(v: string) {}
}
// error
class MyClass extends mixin(BaseClass) {
get name() {
~~~~
!!! error TS2611: 'name' is defined as a property in class 'mixin<typeof BaseClass>.(Anonymous class) & BaseClass', but is overridden here in 'MyClass' as an accessor.
return "";
}
}

View File

@@ -0,0 +1,62 @@
//// [tests/cases/conformance/classes/mixinAccessors3.ts] ////
//// [mixinAccessors3.ts]
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
return class extends superclass {
get name() {
return "";
}
};
}
class BaseClass {
set name(v: string) {}
}
// error
class MyClass extends mixin(BaseClass) {
get name() {
return "";
}
}
//// [mixinAccessors3.js]
"use strict";
function mixin(superclass) {
return class extends superclass {
get name() {
return "";
}
};
}
class BaseClass {
set name(v) { }
}
// error
class MyClass extends mixin(BaseClass) {
get name() {
return "";
}
}
//// [mixinAccessors3.d.ts]
declare function mixin<T extends {
new (...args: any[]): {};
}>(superclass: T): {
new (...args: any[]): {
get name(): string;
};
} & T;
declare class BaseClass {
set name(v: string);
}
declare const MyClass_base: {
new (...args: any[]): {
get name(): string;
};
} & typeof BaseClass;
declare class MyClass extends MyClass_base {
get name(): string;
}

View File

@@ -0,0 +1,42 @@
//// [tests/cases/conformance/classes/mixinAccessors3.ts] ////
=== mixinAccessors3.ts ===
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
>mixin : Symbol(mixin, Decl(mixinAccessors3.ts, 0, 0))
>T : Symbol(T, Decl(mixinAccessors3.ts, 0, 15))
>args : Symbol(args, Decl(mixinAccessors3.ts, 0, 32))
>superclass : Symbol(superclass, Decl(mixinAccessors3.ts, 0, 55))
>T : Symbol(T, Decl(mixinAccessors3.ts, 0, 15))
return class extends superclass {
>superclass : Symbol(superclass, Decl(mixinAccessors3.ts, 0, 55))
get name() {
>name : Symbol((Anonymous class).name, Decl(mixinAccessors3.ts, 1, 35))
return "";
}
};
}
class BaseClass {
>BaseClass : Symbol(BaseClass, Decl(mixinAccessors3.ts, 6, 1))
set name(v: string) {}
>name : Symbol(BaseClass.name, Decl(mixinAccessors3.ts, 8, 17))
>v : Symbol(v, Decl(mixinAccessors3.ts, 9, 11))
}
// error
class MyClass extends mixin(BaseClass) {
>MyClass : Symbol(MyClass, Decl(mixinAccessors3.ts, 10, 1))
>mixin : Symbol(mixin, Decl(mixinAccessors3.ts, 0, 0))
>BaseClass : Symbol(BaseClass, Decl(mixinAccessors3.ts, 6, 1))
get name() {
>name : Symbol(MyClass.name, Decl(mixinAccessors3.ts, 13, 40))
return "";
}
}

View File

@@ -0,0 +1,60 @@
//// [tests/cases/conformance/classes/mixinAccessors3.ts] ////
=== mixinAccessors3.ts ===
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
>mixin : <T extends { new (...args: any[]): {}; }>(superclass: T) => { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>args : any[]
> : ^^^^^
>superclass : T
> : ^
return class extends superclass {
>class extends superclass { get name() { return ""; } } : { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T
> : ^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>superclass : {}
> : ^^
get name() {
>name : string
> : ^^^^^^
return "";
>"" : ""
> : ^^
}
};
}
class BaseClass {
>BaseClass : BaseClass
> : ^^^^^^^^^
set name(v: string) {}
>name : string
> : ^^^^^^
>v : string
> : ^^^^^^
}
// error
class MyClass extends mixin(BaseClass) {
>MyClass : MyClass
> : ^^^^^^^
>mixin(BaseClass) : mixin<typeof BaseClass>.(Anonymous class) & BaseClass
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>mixin : <T extends { new (...args: any[]): {}; }>(superclass: T) => { new (...args: any[]): (Anonymous class); prototype: mixin<any>.(Anonymous class); } & T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>BaseClass : typeof BaseClass
> : ^^^^^^^^^^^^^^^^
get name() {
>name : string
> : ^^^^^^
return "";
>"" : ""
> : ^^
}
}

View File

@@ -0,0 +1,68 @@
//// [tests/cases/conformance/classes/mixinAccessors4.ts] ////
//// [mixinAccessors4.ts]
// https://github.com/microsoft/TypeScript/issues/44938
class A {
constructor(...args: any[]) {}
get myName(): string {
return "A";
}
}
function Mixin<T extends typeof A>(Super: T) {
return class B extends Super {
get myName(): string {
return "B";
}
};
}
class C extends Mixin(A) {
get myName(): string {
return "C";
}
}
//// [mixinAccessors4.js]
"use strict";
// https://github.com/microsoft/TypeScript/issues/44938
class A {
constructor(...args) { }
get myName() {
return "A";
}
}
function Mixin(Super) {
return class B extends Super {
get myName() {
return "B";
}
};
}
class C extends Mixin(A) {
get myName() {
return "C";
}
}
//// [mixinAccessors4.d.ts]
declare class A {
constructor(...args: any[]);
get myName(): string;
}
declare function Mixin<T extends typeof A>(Super: T): {
new (...args: any[]): {
get myName(): string;
};
} & T;
declare const C_base: {
new (...args: any[]): {
get myName(): string;
};
} & typeof A;
declare class C extends C_base {
get myName(): string;
}

View File

@@ -0,0 +1,49 @@
//// [tests/cases/conformance/classes/mixinAccessors4.ts] ////
=== mixinAccessors4.ts ===
// https://github.com/microsoft/TypeScript/issues/44938
class A {
>A : Symbol(A, Decl(mixinAccessors4.ts, 0, 0))
constructor(...args: any[]) {}
>args : Symbol(args, Decl(mixinAccessors4.ts, 3, 14))
get myName(): string {
>myName : Symbol(A.myName, Decl(mixinAccessors4.ts, 3, 32))
return "A";
}
}
function Mixin<T extends typeof A>(Super: T) {
>Mixin : Symbol(Mixin, Decl(mixinAccessors4.ts, 7, 1))
>T : Symbol(T, Decl(mixinAccessors4.ts, 9, 15))
>A : Symbol(A, Decl(mixinAccessors4.ts, 0, 0))
>Super : Symbol(Super, Decl(mixinAccessors4.ts, 9, 35))
>T : Symbol(T, Decl(mixinAccessors4.ts, 9, 15))
return class B extends Super {
>B : Symbol(B, Decl(mixinAccessors4.ts, 10, 8))
>Super : Symbol(Super, Decl(mixinAccessors4.ts, 9, 35))
get myName(): string {
>myName : Symbol(B.myName, Decl(mixinAccessors4.ts, 10, 32))
return "B";
}
};
}
class C extends Mixin(A) {
>C : Symbol(C, Decl(mixinAccessors4.ts, 15, 1))
>Mixin : Symbol(Mixin, Decl(mixinAccessors4.ts, 7, 1))
>A : Symbol(A, Decl(mixinAccessors4.ts, 0, 0))
get myName(): string {
>myName : Symbol(C.myName, Decl(mixinAccessors4.ts, 17, 26))
return "C";
}
}

View File

@@ -0,0 +1,70 @@
//// [tests/cases/conformance/classes/mixinAccessors4.ts] ////
=== mixinAccessors4.ts ===
// https://github.com/microsoft/TypeScript/issues/44938
class A {
>A : A
> : ^
constructor(...args: any[]) {}
>args : any[]
> : ^^^^^
get myName(): string {
>myName : string
> : ^^^^^^
return "A";
>"A" : "A"
> : ^^^
}
}
function Mixin<T extends typeof A>(Super: T) {
>Mixin : <T extends typeof A>(Super: T) => { new (...args: any[]): B; prototype: Mixin<any>.B; } & T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>A : typeof A
> : ^^^^^^^^
>Super : T
> : ^
return class B extends Super {
>class B extends Super { get myName(): string { return "B"; } } : { new (...args: any[]): B; prototype: Mixin<any>.B; } & T
> : ^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>B : { new (...args: any[]): B; prototype: Mixin<any>.B; } & T
> : ^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>Super : A
> : ^
get myName(): string {
>myName : string
> : ^^^^^^
return "B";
>"B" : "B"
> : ^^^
}
};
}
class C extends Mixin(A) {
>C : C
> : ^
>Mixin(A) : Mixin<typeof A>.B & A
> : ^^^^^^^^^^^^^^^^^^^^^
>Mixin : <T extends typeof A>(Super: T) => { new (...args: any[]): B; prototype: Mixin<any>.B; } & T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>A : typeof A
> : ^^^^^^^^
get myName(): string {
>myName : string
> : ^^^^^^
return "C";
>"C" : "C"
> : ^^^
}
}

View File

@@ -0,0 +1,46 @@
//// [tests/cases/conformance/classes/mixinAccessors5.ts] ////
//// [mixinAccessors5.ts]
// https://github.com/microsoft/TypeScript/issues/61967
declare function basicMixin<T extends object, U extends object>(
t: T,
u: U,
): T & U;
declare class GetterA {
constructor(...args: any[]);
get inCompendium(): boolean;
}
declare class GetterB {
constructor(...args: any[]);
get inCompendium(): boolean;
}
declare class TestB extends basicMixin(GetterA, GetterB) {
override get inCompendium(): boolean;
}
//// [mixinAccessors5.js]
"use strict";
// https://github.com/microsoft/TypeScript/issues/61967
//// [mixinAccessors5.d.ts]
declare function basicMixin<T extends object, U extends object>(t: T, u: U): T & U;
declare class GetterA {
constructor(...args: any[]);
get inCompendium(): boolean;
}
declare class GetterB {
constructor(...args: any[]);
get inCompendium(): boolean;
}
declare const TestB_base: typeof GetterA & typeof GetterB;
declare class TestB extends TestB_base {
get inCompendium(): boolean;
}

View File

@@ -0,0 +1,52 @@
//// [tests/cases/conformance/classes/mixinAccessors5.ts] ////
=== mixinAccessors5.ts ===
// https://github.com/microsoft/TypeScript/issues/61967
declare function basicMixin<T extends object, U extends object>(
>basicMixin : Symbol(basicMixin, Decl(mixinAccessors5.ts, 0, 0))
>T : Symbol(T, Decl(mixinAccessors5.ts, 2, 28))
>U : Symbol(U, Decl(mixinAccessors5.ts, 2, 45))
t: T,
>t : Symbol(t, Decl(mixinAccessors5.ts, 2, 64))
>T : Symbol(T, Decl(mixinAccessors5.ts, 2, 28))
u: U,
>u : Symbol(u, Decl(mixinAccessors5.ts, 3, 7))
>U : Symbol(U, Decl(mixinAccessors5.ts, 2, 45))
): T & U;
>T : Symbol(T, Decl(mixinAccessors5.ts, 2, 28))
>U : Symbol(U, Decl(mixinAccessors5.ts, 2, 45))
declare class GetterA {
>GetterA : Symbol(GetterA, Decl(mixinAccessors5.ts, 5, 9))
constructor(...args: any[]);
>args : Symbol(args, Decl(mixinAccessors5.ts, 8, 14))
get inCompendium(): boolean;
>inCompendium : Symbol(GetterA.inCompendium, Decl(mixinAccessors5.ts, 8, 30))
}
declare class GetterB {
>GetterB : Symbol(GetterB, Decl(mixinAccessors5.ts, 11, 1))
constructor(...args: any[]);
>args : Symbol(args, Decl(mixinAccessors5.ts, 14, 14))
get inCompendium(): boolean;
>inCompendium : Symbol(GetterB.inCompendium, Decl(mixinAccessors5.ts, 14, 30))
}
declare class TestB extends basicMixin(GetterA, GetterB) {
>TestB : Symbol(TestB, Decl(mixinAccessors5.ts, 17, 1))
>basicMixin : Symbol(basicMixin, Decl(mixinAccessors5.ts, 0, 0))
>GetterA : Symbol(GetterA, Decl(mixinAccessors5.ts, 5, 9))
>GetterB : Symbol(GetterB, Decl(mixinAccessors5.ts, 11, 1))
override get inCompendium(): boolean;
>inCompendium : Symbol(TestB.inCompendium, Decl(mixinAccessors5.ts, 19, 58))
}

View File

@@ -0,0 +1,62 @@
//// [tests/cases/conformance/classes/mixinAccessors5.ts] ////
=== mixinAccessors5.ts ===
// https://github.com/microsoft/TypeScript/issues/61967
declare function basicMixin<T extends object, U extends object>(
>basicMixin : <T extends object, U extends object>(t: T, u: U) => T & U
> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^
t: T,
>t : T
> : ^
u: U,
>u : U
> : ^
): T & U;
declare class GetterA {
>GetterA : GetterA
> : ^^^^^^^
constructor(...args: any[]);
>args : any[]
> : ^^^^^
get inCompendium(): boolean;
>inCompendium : boolean
> : ^^^^^^^
}
declare class GetterB {
>GetterB : GetterB
> : ^^^^^^^
constructor(...args: any[]);
>args : any[]
> : ^^^^^
get inCompendium(): boolean;
>inCompendium : boolean
> : ^^^^^^^
}
declare class TestB extends basicMixin(GetterA, GetterB) {
>TestB : TestB
> : ^^^^^
>basicMixin(GetterA, GetterB) : GetterA & GetterB
> : ^^^^^^^^^^^^^^^^^
>basicMixin : <T extends object, U extends object>(t: T, u: U) => T & U
> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^
>GetterA : typeof GetterA
> : ^^^^^^^^^^^^^^
>GetterB : typeof GetterB
> : ^^^^^^^^^^^^^^
override get inCompendium(): boolean;
>inCompendium : boolean
> : ^^^^^^^
}

View File

@@ -0,0 +1,18 @@
// @strict: true
// @target: esnext
// @declaration: true
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
return class extends superclass {};
}
export function wrapper<T>(value: T) {
class BaseClass {
accessor name = value;
}
return class MyClass extends mixin(BaseClass) {
accessor name = value;
}
}
export const Cls = wrapper("test");

View File

@@ -0,0 +1,26 @@
// @strict: true
// @target: esnext
// @lib: dom,esnext
// @declaration: true
// https://github.com/microsoft/TypeScript/issues/58790
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
return class extends superclass {
get validationTarget(): HTMLElement {
return document.createElement("input");
}
};
}
class BaseClass {
get validationTarget(): HTMLElement {
return document.createElement("div");
}
}
class MyClass extends mixin(BaseClass) {
get validationTarget(): HTMLElement {
return document.createElement("select");
}
}

View File

@@ -0,0 +1,17 @@
// @strict: true
// @target: esnext
// @declaration: true
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
return class extends superclass {
accessor name = "";
};
}
class BaseClass {
accessor name = "";
}
class MyClass extends mixin(BaseClass) {
accessor name = "";
}

View File

@@ -0,0 +1,22 @@
// @strict: true
// @target: esnext
// @declaration: true
function mixin<T extends { new (...args: any[]): {} }>(superclass: T) {
return class extends superclass {
get name() {
return "";
}
};
}
class BaseClass {
set name(v: string) {}
}
// error
class MyClass extends mixin(BaseClass) {
get name() {
return "";
}
}

View File

@@ -0,0 +1,26 @@
// @strict: true
// @target: esnext
// @declaration: true
// https://github.com/microsoft/TypeScript/issues/44938
class A {
constructor(...args: any[]) {}
get myName(): string {
return "A";
}
}
function Mixin<T extends typeof A>(Super: T) {
return class B extends Super {
get myName(): string {
return "B";
}
};
}
class C extends Mixin(A) {
get myName(): string {
return "C";
}
}

View File

@@ -0,0 +1,27 @@
// @strict: true
// @target: esnext
// @declaration: true
// https://github.com/microsoft/TypeScript/issues/61967
declare function basicMixin<T extends object, U extends object>(
t: T,
u: U,
): T & U;
declare class GetterA {
constructor(...args: any[]);
get inCompendium(): boolean;
}
declare class GetterB {
constructor(...args: any[]);
get inCompendium(): boolean;
}
declare class TestB extends basicMixin(GetterA, GetterB) {
override get inCompendium(): boolean;
}

View File

@@ -0,0 +1,25 @@
// @strict: true
// @target: esnext
// @declaration: true
export abstract class Base {
accessor a = 1;
}
export function middle(Super = Base) {
abstract class Middle extends Super {}
return Middle;
}
class A {
constructor(...args: any[]) {}
}
export function Mixin<T extends typeof A>(Super: T) {
return class B extends Super {
get myName(): string {
return "B";
}
set myName(arg: string) {}
};
}