Skip to content

Commit a0fa8ae

Browse files
committed
Address most PR comments
I am still working on the error for class expressions that extend from a non-exported base.
1 parent e770249 commit a0fa8ae

File tree

6 files changed

+53
-24
lines changed

6 files changed

+53
-24
lines changed

src/compiler/checker.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3154,7 +3154,7 @@ namespace ts {
31543154
}
31553155

31563156
function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) {
3157-
const globalFlagsToPass = globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike;
3157+
const globalFlagsToPass = globalFlags & (TypeFormatFlags.WriteOwnNameForAnyLike | TypeFormatFlags.WriteClassExpressionAsTypeLiteral);
31583158
let inObjectTypeLiteral = false;
31593159
return writeType(type, globalFlags);
31603160

@@ -3266,7 +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) {
3269+
else if (flags & TypeFormatFlags.WriteClassExpressionAsTypeLiteral &&
3270+
type.symbol.valueDeclaration &&
3271+
type.symbol.valueDeclaration.kind === SyntaxKind.ClassExpression) {
32703272
writeAnonymousType(getDeclaredTypeOfClassOrInterface(type.symbol), flags);
32713273
}
32723274
else {
@@ -3316,7 +3318,9 @@ namespace ts {
33163318
const symbol = type.symbol;
33173319
if (symbol) {
33183320
// Always use 'typeof T' for type of class, enum, and module objects
3319-
if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) && symbol.valueDeclaration.kind !== SyntaxKind.ClassExpression ||
3321+
if (symbol.flags & SymbolFlags.Class &&
3322+
!getBaseTypeVariableOfClass(symbol) &&
3323+
!(symbol.valueDeclaration.kind === SyntaxKind.ClassExpression && flags & TypeFormatFlags.WriteClassExpressionAsTypeLiteral) ||
33203324
symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule)) {
33213325
writeTypeOfSymbol(type, flags);
33223326
}
@@ -3348,6 +3352,8 @@ namespace ts {
33483352
getObjectFlags(type) & ObjectFlags.Anonymous &&
33493353
type.symbol && type.symbol.flags & SymbolFlags.Class;
33503354
if (isConstructorObject) {
3355+
// TODO: something needs to issue accessibility errors (here, I think)
3356+
// before writing a literal type that flattens base types, check that the base types are accessible
33513357
writeLiteralType(type, flags);
33523358
}
33533359
else {
@@ -3473,6 +3479,11 @@ namespace ts {
34733479
buildIndexSignatureDisplay(resolved.stringIndexInfo, writer, IndexKind.String, enclosingDeclaration, globalFlags, symbolStack);
34743480
buildIndexSignatureDisplay(resolved.numberIndexInfo, writer, IndexKind.Number, enclosingDeclaration, globalFlags, symbolStack);
34753481
for (const p of resolved.properties) {
3482+
if (globalFlags & TypeFormatFlags.WriteClassExpressionAsTypeLiteral &&
3483+
(p.name === "prototype" ||
3484+
getDeclarationModifierFlagsFromSymbol(p) & (ModifierFlags.Private | ModifierFlags.Protected))) {
3485+
continue;
3486+
}
34763487
const t = getTypeOfSymbol(p);
34773488
if (p.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(t).length) {
34783489
const signatures = getSignaturesOfType(t, SignatureKind.Call);
@@ -3487,7 +3498,7 @@ namespace ts {
34873498
writePropertyWithModifiers(p);
34883499
writePunctuation(writer, SyntaxKind.ColonToken);
34893500
writeSpace(writer);
3490-
writeType(t, TypeFormatFlags.None);
3501+
writeType(t, globalFlags & TypeFormatFlags.WriteClassExpressionAsTypeLiteral);
34913502
writePunctuation(writer, SyntaxKind.SemicolonToken);
34923503
writer.writeLine();
34933504
}

src/compiler/declarationEmitter.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,9 @@ namespace ts {
344344
}
345345
else {
346346
errorNameNode = declaration.name;
347-
const format = TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue |
347+
const format = TypeFormatFlags.UseTypeOfFunction |
348+
TypeFormatFlags.WriteClassExpressionAsTypeLiteral |
349+
TypeFormatFlags.UseTypeAliasValue |
348350
(shouldUseResolverType ? TypeFormatFlags.AddUndefined : 0);
349351
resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, format, writer);
350352
errorNameNode = undefined;
@@ -360,7 +362,11 @@ namespace ts {
360362
}
361363
else {
362364
errorNameNode = signature.name;
363-
resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
365+
resolver.writeReturnTypeOfSignatureDeclaration(
366+
signature,
367+
enclosingDeclaration,
368+
TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue | TypeFormatFlags.WriteClassExpressionAsTypeLiteral,
369+
writer);
364370
errorNameNode = undefined;
365371
}
366372
}
@@ -621,7 +627,11 @@ namespace ts {
621627
write(tempVarName);
622628
write(": ");
623629
writer.getSymbolAccessibilityDiagnostic = () => diagnostic;
624-
resolver.writeTypeOfExpression(expr, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
630+
resolver.writeTypeOfExpression(
631+
expr,
632+
enclosingDeclaration,
633+
TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue | TypeFormatFlags.WriteClassExpressionAsTypeLiteral,
634+
writer);
625635
write(";");
626636
writeLine();
627637
return tempVarName;

src/compiler/types.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,20 +2652,21 @@ namespace ts {
26522652
}
26532653

26542654
export const enum TypeFormatFlags {
2655-
None = 0x00000000,
2656-
WriteArrayAsGenericType = 0x00000001, // Write Array<T> instead T[]
2657-
UseTypeOfFunction = 0x00000002, // Write typeof instead of function type literal
2658-
NoTruncation = 0x00000004, // Don't truncate typeToString result
2659-
WriteArrowStyleSignature = 0x00000008, // Write arrow style signature
2660-
WriteOwnNameForAnyLike = 0x00000010, // Write symbol's own name instead of 'any' for any like types (eg. unknown, __resolving__ etc)
2661-
WriteTypeArgumentsOfSignature = 0x00000020, // Write the type arguments instead of type parameters of the signature
2662-
InElementType = 0x00000040, // Writing an array or union element type
2663-
UseFullyQualifiedType = 0x00000080, // Write out the fully qualified type name (eg. Module.Type, instead of Type)
2664-
InFirstTypeArgument = 0x00000100, // Writing first type argument of the instantiated type
2665-
InTypeAlias = 0x00000200, // Writing type in type alias declaration
2666-
UseTypeAliasValue = 0x00000400, // Serialize the type instead of using type-alias. This is needed when we emit declaration file.
2667-
SuppressAnyReturnType = 0x00000800, // If the return type is any-like, don't offer a return type.
2668-
AddUndefined = 0x00001000, // Add undefined to types of initialized, non-optional parameters
2655+
None = 0,
2656+
WriteArrayAsGenericType = 1 << 0, // Write Array<T> instead T[]
2657+
UseTypeOfFunction = 1 << 2, // Write typeof instead of function type literal
2658+
NoTruncation = 1 << 3, // Don't truncate typeToString result
2659+
WriteArrowStyleSignature = 1 << 4, // Write arrow style signature
2660+
WriteOwnNameForAnyLike = 1 << 5, // Write symbol's own name instead of 'any' for any like types (eg. unknown, __resolving__ etc)
2661+
WriteTypeArgumentsOfSignature = 1 << 6, // Write the type arguments instead of type parameters of the signature
2662+
InElementType = 1 << 7, // Writing an array or union element type
2663+
UseFullyQualifiedType = 1 << 8, // Write out the fully qualified type name (eg. Module.Type, instead of Type)
2664+
InFirstTypeArgument = 1 << 9, // Writing first type argument of the instantiated type
2665+
InTypeAlias = 1 << 10, // Writing type in type alias declaration
2666+
UseTypeAliasValue = 1 << 11, // Serialize the type instead of using type-alias. This is needed when we emit declaration file.
2667+
SuppressAnyReturnType = 1 << 12, // If the return type is any-like, don't offer a return type.
2668+
AddUndefined = 1 << 13, // Add undefined to types of initialized, non-optional parameters
2669+
WriteClassExpressionAsTypeLiteral = 1 << 14, // Write a type literal instead of (Anonymous class)
26692670
}
26702671

26712672
export const enum SymbolFormatFlags {

tests/cases/compiler/emitClassExpressionInDeclarationFile.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@
22
export var simpleExample = class {
33
static getTags() { }
44
tags() { }
5+
private static ps = -1
6+
private p = 12
57
}
68
export var circularReference = class C {
79
static getTags(c: C): C { return c }
810
tags(c: C): C { return c }
911
}
1012

13+
class Base { }
14+
export function foo() {
15+
return class extends Base { }
16+
}
17+
1118
// repro from #15066
1219
export class FooItem {
1320
foo(): void { }

tests/cases/fourslash/findAllRefsForVariableInExtendsClause01.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
////var [|{| "isWriteAccess": true, "isDefinition": true |}Base|] = class { };
44
////class C extends [|Base|] { }
55

6-
verify.singleReferenceGroup("var Base: {\n new (): {};\n prototype: {};\n}");
6+
verify.singleReferenceGroup("var Base: typeof Base");

tests/cases/fourslash/renameJsExports02.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
const [r0, r1] = test.ranges();
1111
verify.referenceGroups(r0, [
1212
{ definition: "(local class) A", ranges: [r0] },
13-
{ definition: "const A: {\n new (): {};\n prototype: {};\n}", ranges: [r1] }
13+
{ definition: "const A: typeof A", ranges: [r1] }
1414
]);
1515

16-
verify.singleReferenceGroup("const A: {\n new (): {};\n prototype: {};\n}", [r1]);
16+
verify.singleReferenceGroup("const A: typeof A", [r1]);

0 commit comments

Comments
 (0)