diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 7c41bcccc3e7a..7779359da5f3a 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1657,38 +1657,34 @@ export function transformDeclarations(context: TransformationContext): Transform const extendsClause = getEffectiveBaseTypeNode(input); if (extendsClause && !isEntityNameExpression(extendsClause.expression) && extendsClause.expression.kind !== SyntaxKind.NullKeyword) { - // We must add a temporary declaration for the extends clause expression + // For classes which get their base type from an expression other than a name or Null, replace the expression they extend with one of the form: + // declare class A extends ({} as DEFINITION_OF_BASE_HERE) {} - const oldId = input.name ? unescapeLeadingUnderscores(input.name.escapedText) : "default"; - const newId = factory.createUniqueName(`${oldId}_base`, GeneratedIdentifierFlags.Optimistic); getSymbolAccessibilityDiagnostic = () => ({ diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1, errorNode: extendsClause, typeName: input.name, }); - const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); - const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const)); + const baseType = resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker); + const extendsExpression = factory.createAsExpression(factory.createObjectLiteralExpression(), baseType!); // TODO: GH#18217 const heritageClauses = factory.createNodeArray(map(input.heritageClauses, clause => { if (clause.token === SyntaxKind.ExtendsKeyword) { const oldDiag = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(clause.types[0]); - const newClause = factory.updateHeritageClause(clause, map(clause.types, t => factory.updateExpressionWithTypeArguments(t, newId, visitNodes(t.typeArguments, visitDeclarationSubtree, isTypeNode)))); + const newClause = factory.updateHeritageClause(clause, map(clause.types, t => factory.updateExpressionWithTypeArguments(t, extendsExpression, visitNodes(t.typeArguments, visitDeclarationSubtree, isTypeNode)))); getSymbolAccessibilityDiagnostic = oldDiag; return newClause; } return factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => isEntityNameExpression(t.expression) || t.expression.kind === SyntaxKind.NullKeyword)), visitDeclarationSubtree, isExpressionWithTypeArguments)); })); - return [ - statement, - cleanup(factory.updateClassDeclaration( - input, - modifiers, - input.name, - typeParameters, - heritageClauses, - members, - ))!, - ]; // TODO: GH#18217 + return cleanup(factory.updateClassDeclaration( + input, + modifiers, + input.name, + typeParameters, + heritageClauses, + members, + )); } else { const heritageClauses = transformHeritageClauses(input.heritageClauses); diff --git a/tests/baselines/reference/amdDeclarationEmitNoExtraDeclare.js b/tests/baselines/reference/amdDeclarationEmitNoExtraDeclare.js index ad02552328f0e..bd5192f19cedc 100644 --- a/tests/baselines/reference/amdDeclarationEmitNoExtraDeclare.js +++ b/tests/baselines/reference/amdDeclarationEmitNoExtraDeclare.js @@ -86,7 +86,6 @@ declare module "Configurable" { declare module "Class" { export class HiddenClass { } - const ActualClass_base: typeof HiddenClass; - export class ActualClass extends ActualClass_base { + export class ActualClass extends ({} as typeof HiddenClass) { } } diff --git a/tests/baselines/reference/anonClassDeclarationEmitIsAnon.js b/tests/baselines/reference/anonClassDeclarationEmitIsAnon.js index 2c0dc04e17776..d69d45b6e3eef 100644 --- a/tests/baselines/reference/anonClassDeclarationEmitIsAnon.js +++ b/tests/baselines/reference/anonClassDeclarationEmitIsAnon.js @@ -137,11 +137,10 @@ export default _default; export declare class User { name: string; } -declare const TimestampedUser_base: { +export declare class TimestampedUser extends ({} as { new (...args: any[]): { timestamp: number; }; -} & typeof User; -export declare class TimestampedUser extends TimestampedUser_base { +} & typeof User) { constructor(); } diff --git a/tests/baselines/reference/classReferencedInContextualParameterWithinItsOwnBaseExpression.js b/tests/baselines/reference/classReferencedInContextualParameterWithinItsOwnBaseExpression.js index 8674d45fd0b91..11df41642717e 100644 --- a/tests/baselines/reference/classReferencedInContextualParameterWithinItsOwnBaseExpression.js +++ b/tests/baselines/reference/classReferencedInContextualParameterWithinItsOwnBaseExpression.js @@ -60,9 +60,8 @@ type OutputFrom = { [K in keyof TFields]: "_TOutput" extends keyof TFields[K] ? TFields[K]["_TOutput"] : never; }; declare function string(): Type; -declare const A_base: Class>; -export declare class A extends A_base { +}>>) { } export {}; diff --git a/tests/baselines/reference/declarationEmitClassMixinLocalClassDeclaration.js b/tests/baselines/reference/declarationEmitClassMixinLocalClassDeclaration.js index 9ac2030ef1623..821269704c4d9 100644 --- a/tests/baselines/reference/declarationEmitClassMixinLocalClassDeclaration.js +++ b/tests/baselines/reference/declarationEmitClassMixinLocalClassDeclaration.js @@ -80,11 +80,10 @@ type MixinHelperFunc = (required: [A], arg: T) => T export declare const Mixin: MixinHelperFunc; export declare class Base { } -declare const XmlElement2_base: { +export declare class XmlElement2 extends ({} as { new (): { num: number; }; -}; -export declare class XmlElement2 extends XmlElement2_base { +}) { } export {}; diff --git a/tests/baselines/reference/declarationEmitExpressionInExtends2.js b/tests/baselines/reference/declarationEmitExpressionInExtends2.js index e7ee7c34a4100..7ff1b7999f677 100644 --- a/tests/baselines/reference/declarationEmitExpressionInExtends2.js +++ b/tests/baselines/reference/declarationEmitExpressionInExtends2.js @@ -52,6 +52,5 @@ declare class C { y: U; } declare function getClass(c: T): typeof C; -declare const MyClass_base: typeof C; -declare class MyClass extends MyClass_base { +declare class MyClass extends ({} as typeof C) { } diff --git a/tests/baselines/reference/declarationEmitExpressionInExtends3.js b/tests/baselines/reference/declarationEmitExpressionInExtends3.js index c102652410aef..a1f231768a3cb 100644 --- a/tests/baselines/reference/declarationEmitExpressionInExtends3.js +++ b/tests/baselines/reference/declarationEmitExpressionInExtends3.js @@ -128,16 +128,12 @@ export interface ExportedInterface { interface LocalInterface { x: number; } -declare const MyClass_base: typeof LocalClass; -export declare class MyClass extends MyClass_base { +export declare class MyClass extends ({} as typeof LocalClass) { } -declare const MyClass2_base: typeof ExportedClass; -export declare class MyClass2 extends MyClass2_base { +export declare class MyClass2 extends ({} as typeof ExportedClass) { } -declare const MyClass3_base: typeof ExportedClass; -export declare class MyClass3 extends MyClass3_base { +export declare class MyClass3 extends ({} as typeof ExportedClass) { } -declare const MyClass4_base: typeof ExportedClass; -export declare class MyClass4 extends MyClass4_base { +export declare class MyClass4 extends ({} as typeof ExportedClass) { } export {}; diff --git a/tests/baselines/reference/declarationEmitExpressionInExtends4.js b/tests/baselines/reference/declarationEmitExpressionInExtends4.js index a5d57ceb73c95..795965745f291 100644 --- a/tests/baselines/reference/declarationEmitExpressionInExtends4.js +++ b/tests/baselines/reference/declarationEmitExpressionInExtends4.js @@ -68,13 +68,11 @@ var C3 = /** @class */ (function (_super) { declare function getSomething(): { new (): {}; }; -declare const C_base: { +declare class C extends ({} as { new (): {}; -}; -declare class C extends C_base { +}) { } -declare const C2_base: any; -declare class C2 extends C2_base { +declare class C2 extends ({} as any) { } declare class C3 extends SomeUndefinedFunction { } diff --git a/tests/baselines/reference/declarationEmitExpressionInExtends5.js b/tests/baselines/reference/declarationEmitExpressionInExtends5.js index 19659fdefec3f..5e52b58f67f76 100644 --- a/tests/baselines/reference/declarationEmitExpressionInExtends5.js +++ b/tests/baselines/reference/declarationEmitExpressionInExtends5.js @@ -63,13 +63,11 @@ var Test; //// [declarationEmitExpressionInExtends5.d.ts] declare namespace Test { - export interface IFace { + interface IFace { } - export class SomeClass implements IFace { + class SomeClass implements IFace { } - const Derived_base: new () => IFace; - export class Derived extends Derived_base { + class Derived extends ({} as new () => IFace) { } - export function getClass(): new () => T; - export {}; + function getClass(): new () => T; } diff --git a/tests/baselines/reference/declarationEmitForDefaultExportClassExtendingExpression01.js b/tests/baselines/reference/declarationEmitForDefaultExportClassExtendingExpression01.js index 648c22ec1da8d..82cd6712d7f32 100644 --- a/tests/baselines/reference/declarationEmitForDefaultExportClassExtendingExpression01.js +++ b/tests/baselines/reference/declarationEmitForDefaultExportClassExtendingExpression01.js @@ -66,7 +66,6 @@ interface Greeter { interface GreeterConstructor { new (): Greeter; } -declare const default_base: GreeterConstructor; -export default class extends default_base { +export default class extends ({} as GreeterConstructor) { } export {}; diff --git a/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js b/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js index 3e589f2f7a987..47aa9c0ab45e5 100644 --- a/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js +++ b/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js @@ -106,11 +106,9 @@ export declare const Mixed: { bar: number; }; } & typeof Unmixed; -declare const FilteredThing_base: (abstract new (...args: any[]) => { +export declare class FilteredThing extends ({} as (abstract new (...args: any[]) => { match(path: string): boolean; thing: number; -}) & typeof Unmixed; -export declare class FilteredThing extends FilteredThing_base { +}) & typeof Unmixed) { match(path: string): boolean; } -export {}; diff --git a/tests/baselines/reference/declarationNoDanglingGenerics.js b/tests/baselines/reference/declarationNoDanglingGenerics.js index 006417922eaaa..5ddfd09e9be1b 100644 --- a/tests/baselines/reference/declarationNoDanglingGenerics.js +++ b/tests/baselines/reference/declarationNoDanglingGenerics.js @@ -107,28 +107,24 @@ exports.CKind = CKind; //// [declarationNoDanglingGenerics.d.ts] -declare const AKind_base: { +export declare class AKind extends ({} as { new (): { readonly kind: "A"; }; readonly THE_KIND: "A"; -}; -export declare class AKind extends AKind_base { +}) { } -declare const BKind_base: { +export declare class BKind extends ({} as { new (): { readonly kind: "B"; }; readonly THE_KIND: "B"; -}; -export declare class BKind extends BKind_base { +}) { } -declare const CKind_base: { +export declare class CKind extends ({} as { new (): { readonly kind: "C"; }; readonly THE_KIND: "C"; -}; -export declare class CKind extends CKind_base { +}) { } -export {}; diff --git a/tests/baselines/reference/emitClassExpressionInDeclarationFile.js b/tests/baselines/reference/emitClassExpressionInDeclarationFile.js index c77c114490044..e2dfc834ee862 100644 --- a/tests/baselines/reference/emitClassExpressionInDeclarationFile.js +++ b/tests/baselines/reference/emitClassExpressionInDeclarationFile.js @@ -128,14 +128,12 @@ export declare function WithTags>(Base: T): { }; getTags(): void; } & T; -declare const Test_base: { +export declare class Test extends ({} as { new (...args: any[]): { tags(): void; foo(): void; name?: string; }; getTags(): void; -} & typeof FooItem; -export declare class Test extends Test_base { +} & typeof FooItem) { } -export {}; diff --git a/tests/baselines/reference/exportClassExtendingIntersection.js b/tests/baselines/reference/exportClassExtendingIntersection.js index ebf41f7c14932..131f58a1f5a96 100644 --- a/tests/baselines/reference/exportClassExtendingIntersection.js +++ b/tests/baselines/reference/exportClassExtendingIntersection.js @@ -126,10 +126,8 @@ export declare function MyMixin>>(base: T //// [FinalClass.d.ts] import { MyBaseClass } from './BaseClass'; import { MyMixin } from './MixinClass'; -declare const MyExtendedClass_base: typeof MyBaseClass & import("./BaseClass").Constructor; -export declare class MyExtendedClass extends MyExtendedClass_base { +export declare class MyExtendedClass extends ({} as typeof MyBaseClass & import("./BaseClass").Constructor) { extendedClassProperty: number; } -export {}; //// [Main.d.ts] export {}; diff --git a/tests/baselines/reference/mixinAbstractClasses.js b/tests/baselines/reference/mixinAbstractClasses.js index e787c467451bf..0990747bbac49 100644 --- a/tests/baselines/reference/mixinAbstractClasses.js +++ b/tests/baselines/reference/mixinAbstractClasses.js @@ -73,12 +73,10 @@ declare class ConcreteBase { declare abstract class AbstractBase { abstract abstractBaseMethod(): void; } -declare const DerivedFromConcrete_base: typeof ConcreteBase & (abstract new (...args: any) => Mixin); -declare class DerivedFromConcrete extends DerivedFromConcrete_base { +declare class DerivedFromConcrete extends ({} as typeof ConcreteBase & (abstract new (...args: any) => Mixin)) { } declare const wasConcrete: DerivedFromConcrete; -declare const DerivedFromAbstract_base: typeof AbstractBase & (abstract new (...args: any) => Mixin); -declare class DerivedFromAbstract extends DerivedFromAbstract_base { +declare class DerivedFromAbstract extends ({} as typeof AbstractBase & (abstract new (...args: any) => Mixin)) { abstractBaseMethod(): void; } declare const wasAbstract: DerivedFromAbstract; diff --git a/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.js b/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.js index 98bfeaf3a3105..11bc1936c7462 100644 --- a/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.js +++ b/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.js @@ -54,12 +54,11 @@ declare function Mixin2 any>(base }) & { staticMixinMethod(): void; }) & TBase; -declare const DerivedFromAbstract2_base: ((abstract new (...args: any[]) => { +declare class DerivedFromAbstract2 extends ({} as ((abstract new (...args: any[]) => { [x: string]: any; mixinMethod(): void; }) & { staticMixinMethod(): void; -}) & typeof AbstractBase; -declare class DerivedFromAbstract2 extends DerivedFromAbstract2_base { +}) & typeof AbstractBase) { abstractBaseMethod(): void; } diff --git a/tests/baselines/reference/mixinAccessModifiers.js b/tests/baselines/reference/mixinAccessModifiers.js index 1effc9954afb8..31e08fd4500e0 100644 --- a/tests/baselines/reference/mixinAccessModifiers.js +++ b/tests/baselines/reference/mixinAccessModifiers.js @@ -360,27 +360,21 @@ declare function f4(x: Protected & Protected2): void; declare function f5(x: Protected & Public): void; declare function f6(x: Public & Public2): void; declare function Mix(c1: T, c2: U): T & U; -declare const C1_base: typeof Private & typeof Private2; -declare class C1 extends C1_base { +declare class C1 extends ({} as typeof Private & typeof Private2) { } -declare const C2_base: typeof Private & typeof Protected; -declare class C2 extends C2_base { +declare class C2 extends ({} as typeof Private & typeof Protected) { } -declare const C3_base: typeof Private & typeof Public; -declare class C3 extends C3_base { +declare class C3 extends ({} as typeof Private & typeof Public) { } -declare const C4_base: typeof Protected & typeof Protected2; -declare class C4 extends C4_base { +declare class C4 extends ({} as typeof Protected & typeof Protected2) { f(c4: C4, c5: C5, c6: C6): void; static g(): void; } -declare const C5_base: typeof Protected & typeof Public; -declare class C5 extends C5_base { +declare class C5 extends ({} as typeof Protected & typeof Public) { f(c4: C4, c5: C5, c6: C6): void; static g(): void; } -declare const C6_base: typeof Public & typeof Public2; -declare class C6 extends C6_base { +declare class C6 extends ({} as typeof Public & typeof Public2) { f(c4: C4, c5: C5, c6: C6): void; static g(): void; } diff --git a/tests/baselines/reference/override1.js b/tests/baselines/reference/override1.js index 6ad18ccc5a119..187fc51655d7a 100644 --- a/tests/baselines/reference/override1.js +++ b/tests/baselines/reference/override1.js @@ -144,13 +144,12 @@ declare function f(): { bar(v: string): void; }; }; -declare const E_base: { +declare class E extends ({} as { new (): { foo(): void; bar(): void; }; -}; -declare class E extends E_base { +}) { foo(): void; bar(): void; baz(): void; diff --git a/tests/baselines/reference/recursiveClassBaseType.js b/tests/baselines/reference/recursiveClassBaseType.js index fbfe9c9dee590..0d5af85533ebc 100644 --- a/tests/baselines/reference/recursiveClassBaseType.js +++ b/tests/baselines/reference/recursiveClassBaseType.js @@ -77,18 +77,16 @@ declare const p: (fn: () => T) => T; declare const Base: (val: T) => { new (): T; }; -declare const C_base: new () => { +declare class C extends ({} as new () => { x: C[]; -}; -declare class C extends C_base { +}) { } declare abstract class Base1 { abstract root(): Derived1; } -declare const Derived1_base: { +declare class Derived1 extends ({} as { new (): { root(): any; }; -}; -declare class Derived1 extends Derived1_base { +}) { } diff --git a/tests/baselines/reference/tsc/declarationEmit/when-using-Windows-paths-and-uppercase-letters.js b/tests/baselines/reference/tsc/declarationEmit/when-using-Windows-paths-and-uppercase-letters.js index 448760fe05df2..8779257333fa0 100644 --- a/tests/baselines/reference/tsc/declarationEmit/when-using-Windows-paths-and-uppercase-letters.js +++ b/tests/baselines/reference/tsc/declarationEmit/when-using-Windows-paths-and-uppercase-letters.js @@ -172,11 +172,9 @@ exports.Sub = Sub; //# sourceMappingURL=main.js.map //// [D:/Work/pkg1/dist/main.d.ts] -declare const Sub_base: import("./utils/type-helpers").MyReturnType; -export declare class Sub extends Sub_base { +export declare class Sub extends ({} as import("./utils/type-helpers").MyReturnType) { id: string; } -export {};