Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f61ec7f

Browse filesBrowse files
committed
Declare synthetic var for class extends expression
Classes that extend expressions will get a synthetic var declaration for the expression. This is required for classes that extend an expression that return an intersection type.
1 parent 88f9a97 commit f61ec7f
Copy full SHA for f61ec7f

2 files changed

+55-30Lines changed: 55 additions & 30 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22645,7 +22645,7 @@ namespace ts {
2264522645
const classType = <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(node));
2264622646
resolveBaseTypesOfClass(classType);
2264722647
const baseType = classType.resolvedBaseTypes.length ? classType.resolvedBaseTypes[0] : unknownType;
22648-
if (!baseType.symbol) {
22648+
if (!baseType.symbol && !(baseType.flags & TypeFlags.Intersection)) {
2264922649
writer.reportIllegalExtends();
2265022650
}
2265122651
getSymbolDisplayBuilder().buildTypeDisplay(baseType, writer, enclosingDeclaration, flags);
Collapse file

‎src/compiler/declarationEmitter.ts‎

Copy file name to clipboardExpand all lines: src/compiler/declarationEmitter.ts
+54-29Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -594,12 +594,11 @@ namespace ts {
594594
emitLines(node.statements);
595595
}
596596

597-
// Return a temp variable name to be used in `export default` statements.
597+
// Return a temp variable name to be used in `export default`/`export class ... extends` statements.
598598
// The temp name will be of the form _default_counter.
599599
// Note that export default is only allowed at most once in a module, so we
600600
// do not need to keep track of created temp names.
601-
function getExportDefaultTempVariableName(): string {
602-
const baseName = "_default";
601+
function getExportTempVariableName(baseName: string): string {
603602
if (!currentIdentifiers.has(baseName)) {
604603
return baseName;
605604
}
@@ -613,24 +612,31 @@ namespace ts {
613612
}
614613
}
615614

615+
function emitTempVariableDeclaration(expr: Expression, baseName: string, diagnostic: SymbolAccessibilityDiagnostic): string {
616+
const tempVarName = getExportTempVariableName(baseName);
617+
if (!noDeclare) {
618+
write("declare ");
619+
}
620+
write("var ");
621+
write(tempVarName);
622+
write(": ");
623+
writer.getSymbolAccessibilityDiagnostic = () => diagnostic;
624+
resolver.writeTypeOfExpression(expr, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
625+
write(";");
626+
writeLine();
627+
return tempVarName;
628+
}
629+
616630
function emitExportAssignment(node: ExportAssignment) {
617631
if (node.expression.kind === SyntaxKind.Identifier) {
618632
write(node.isExportEquals ? "export = " : "export default ");
619633
writeTextOfNode(currentText, node.expression);
620634
}
621635
else {
622-
// Expression
623-
const tempVarName = getExportDefaultTempVariableName();
624-
if (!noDeclare) {
625-
write("declare ");
626-
}
627-
write("var ");
628-
write(tempVarName);
629-
write(": ");
630-
writer.getSymbolAccessibilityDiagnostic = getDefaultExportAccessibilityDiagnostic;
631-
resolver.writeTypeOfExpression(node.expression, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
632-
write(";");
633-
writeLine();
636+
const tempVarName = emitTempVariableDeclaration(node.expression, "_default", {
637+
diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
638+
errorNode: node
639+
});
634640
write(node.isExportEquals ? "export = " : "export default ");
635641
write(tempVarName);
636642
}
@@ -644,13 +650,6 @@ namespace ts {
644650
// write each of these declarations asynchronously
645651
writeAsynchronousModuleElements(nodes);
646652
}
647-
648-
function getDefaultExportAccessibilityDiagnostic(): SymbolAccessibilityDiagnostic {
649-
return {
650-
diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
651-
errorNode: node
652-
};
653-
}
654653
}
655654

656655
function isModuleElementVisible(node: Declaration) {
@@ -1113,7 +1112,11 @@ namespace ts {
11131112
else {
11141113
writer.getSymbolAccessibilityDiagnostic = getHeritageClauseVisibilityError;
11151114
errorNameNode = className;
1116-
resolver.writeBaseConstructorTypeOfClass(<ClassLikeDeclaration>enclosingDeclaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
1115+
resolver.writeBaseConstructorTypeOfClass(
1116+
enclosingDeclaration as ClassLikeDeclaration,
1117+
enclosingDeclaration,
1118+
TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue,
1119+
writer);
11171120
errorNameNode = undefined;
11181121
}
11191122

@@ -1151,21 +1154,39 @@ namespace ts {
11511154
}
11521155
}
11531156

1157+
const prevEnclosingDeclaration = enclosingDeclaration;
1158+
enclosingDeclaration = node;
1159+
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
1160+
let tempVarName: string;
1161+
if (isNonNullExpression(baseTypeNode)) {
1162+
tempVarName = emitTempVariableDeclaration(baseTypeNode.expression, `_${node.name.text}_intersection_base`, {
1163+
diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1,
1164+
errorNode: baseTypeNode,
1165+
typeName: node.name
1166+
});
1167+
}
1168+
11541169
emitJsDocComments(node);
11551170
emitModuleElementDeclarationFlags(node);
11561171
if (hasModifier(node, ModifierFlags.Abstract)) {
11571172
write("abstract ");
11581173
}
1159-
11601174
write("class ");
11611175
writeTextOfNode(currentText, node.name);
1162-
const prevEnclosingDeclaration = enclosingDeclaration;
1163-
enclosingDeclaration = node;
11641176
emitTypeParameters(node.typeParameters);
1165-
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
11661177
if (baseTypeNode) {
1167-
node.name;
1168-
emitHeritageClause(node.name, [baseTypeNode], /*isImplementsList*/ false);
1178+
if (isNonNullExpression(baseTypeNode)) {
1179+
write(" extends ");
1180+
write(tempVarName);
1181+
if (baseTypeNode.typeArguments) {
1182+
write("<");
1183+
emitCommaList(baseTypeNode.typeArguments, emitType);
1184+
write(">");
1185+
}
1186+
}
1187+
else {
1188+
emitHeritageClause(node.name, [baseTypeNode], /*isImplementsList*/ false);
1189+
}
11691190
}
11701191
emitHeritageClause(node.name, getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true);
11711192
write(" {");
@@ -1201,6 +1222,10 @@ namespace ts {
12011222
enclosingDeclaration = prevEnclosingDeclaration;
12021223
}
12031224

1225+
function isNonNullExpression(node: ExpressionWithTypeArguments) {
1226+
return node && !isEntityNameExpression(node.expression) && node.expression.kind !== SyntaxKind.NullKeyword;
1227+
}
1228+
12041229
function emitPropertyDeclaration(node: Declaration) {
12051230
if (hasDynamicName(node)) {
12061231
return;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.