Skip to content

Commit 5a5fee3

Browse files
committed
Declaration-emit class expressions as type literals
This works pretty well. Note that circular references bottom out as `any`. Right now this happens for all type writing, not just for declaration emit, but this is probably an improvement on average.
1 parent fc306ba commit 5a5fee3

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

src/compiler/checker.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3266,6 +3266,9 @@ namespace ts {
32663266
writeTypeList(type.typeArguments.slice(0, getTypeReferenceArity(type)), SyntaxKind.CommaToken);
32673267
writePunctuation(writer, SyntaxKind.CloseBracketToken);
32683268
}
3269+
else if (type.symbol.valueDeclaration && type.symbol.valueDeclaration.kind === SyntaxKind.ClassExpression) {
3270+
writeAnonymousType(getDeclaredTypeOfClassOrInterface(type.symbol), flags);
3271+
}
32693272
else {
32703273
// Write the type reference in the format f<A>.g<B>.C<X, Y> where A and B are type arguments
32713274
// for outer type parameters, and f and g are the respective declaring containers of those
@@ -3313,7 +3316,7 @@ namespace ts {
33133316
const symbol = type.symbol;
33143317
if (symbol) {
33153318
// Always use 'typeof T' for type of class, enum, and module objects
3316-
if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) ||
3319+
if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) && symbol.valueDeclaration.kind !== SyntaxKind.ClassExpression ||
33173320
symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule)) {
33183321
writeTypeOfSymbol(type, flags);
33193322
}
@@ -3335,12 +3338,23 @@ namespace ts {
33353338
else {
33363339
// Since instantiations of the same anonymous type have the same symbol, tracking symbols instead
33373340
// of types allows us to catch circular references to instantiations of the same anonymous type
3341+
// However, in case of class expressions, we want to write both the static side and the instance side.
3342+
// We skip adding the static side so that the instance side has a chance to be written
3343+
// before checking for circular references.
33383344
if (!symbolStack) {
33393345
symbolStack = [];
33403346
}
3341-
symbolStack.push(symbol);
3342-
writeLiteralType(type, flags);
3343-
symbolStack.pop();
3347+
const isConstructorObject = type.flags & TypeFlags.Object &&
3348+
getObjectFlags(type) & ObjectFlags.Anonymous &&
3349+
type.symbol && type.symbol.flags & SymbolFlags.Class;
3350+
if (isConstructorObject) {
3351+
writeLiteralType(type, flags);
3352+
}
3353+
else {
3354+
symbolStack.push(symbol);
3355+
writeLiteralType(type, flags);
3356+
symbolStack.pop();
3357+
}
33443358
}
33453359
}
33463360
else {

0 commit comments

Comments
 (0)