diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 413360d6d2ac2..3efc39739d83c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12534,7 +12534,9 @@ namespace ts { // The expression is processed as an identifier expression (section 4.3) // or property access expression(section 4.10), // the widened type(section 3.9) of which becomes the result. - links.resolvedType = getRegularTypeOfLiteralType(getWidenedType(checkExpression(node.exprName))); + links.resolvedType = node.exprName.kind === SyntaxKind.ClassExpression ? + checkClassExpression(node.exprName) : + getRegularTypeOfLiteralType(getWidenedType(checkExpression(node.exprName))); } return links.resolvedType; } @@ -39040,14 +39042,14 @@ namespace ts { if (flags & ModifierFlags.Abstract) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "abstract"); } - if (node.kind !== SyntaxKind.ClassDeclaration) { + if (node.kind !== SyntaxKind.ClassDeclaration && node.kind !== SyntaxKind.ClassExpression) { if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.GetAccessor && node.kind !== SyntaxKind.SetAccessor) { return grammarErrorOnNode(modifier, Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration); } - if (!(node.parent.kind === SyntaxKind.ClassDeclaration && hasSyntacticModifier(node.parent, ModifierFlags.Abstract))) { + if (!((node.parent.kind === SyntaxKind.ClassDeclaration || node.parent.kind === SyntaxKind.ClassExpression) && hasSyntacticModifier(node.parent, ModifierFlags.Abstract))) { return grammarErrorOnNode(modifier, Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class); } if (flags & ModifierFlags.Static) { @@ -39154,6 +39156,7 @@ namespace ts { case SyntaxKind.FunctionDeclaration: return nodeHasAnyModifiersExcept(node, SyntaxKind.AsyncKeyword); case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: return nodeHasAnyModifiersExcept(node, SyntaxKind.AbstractKeyword); case SyntaxKind.InterfaceDeclaration: case SyntaxKind.VariableStatement: diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 176c9154dcd38..42a02ad3d2bef 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -1733,7 +1733,7 @@ namespace ts { } // @api - function createTypeQueryNode(exprName: EntityName) { + function createTypeQueryNode(exprName: EntityName | ClassExpression) { const node = createBaseNode(SyntaxKind.TypeQuery); node.exprName = exprName; node.transformFlags = TransformFlags.ContainsTypeScript; @@ -1741,7 +1741,7 @@ namespace ts { } // @api - function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName) { + function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName | ClassExpression) { return node.exprName !== exprName ? update(createTypeQueryNode(exprName), node) : node; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 5dcfb5ee07500..0eeb6bfcf2321 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2860,10 +2860,16 @@ namespace ts { return type; } + function isStartOfTypeofClassExpression() { + return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine); + } + function parseTypeQuery(): TypeQueryNode { const pos = getNodePos(); parseExpected(SyntaxKind.TypeOfKeyword); - return finishNode(factory.createTypeQueryNode(parseEntityName(/*allowReservedWords*/ true)), pos); + return finishNode(factory.createTypeQueryNode(isStartOfTypeofClassExpression() ? + doInsideOfContext(NodeFlags.Ambient, parseClassExpression) : + parseEntityName(/*allowReservedWords*/ true)), pos); } function parseTypeParameter(): TypeParameterDeclaration { @@ -5315,6 +5321,11 @@ namespace ts { } return parseFunctionExpression(); + case SyntaxKind.AbstractKeyword: + if (!lookAhead(nextTokenIsClassKeywordOnSameLine)) { + break; + } + // Fall through case SyntaxKind.ClassKeyword: return parseClassExpression(); case SyntaxKind.FunctionKeyword: @@ -6646,7 +6657,10 @@ namespace ts { } function parseClassExpression(): ClassExpression { - return parseClassDeclarationOrExpression(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined, SyntaxKind.ClassExpression); + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); + const modifiers = parseModifiers(); + return parseClassDeclarationOrExpression(pos, hasJSDoc, /*decorators*/ undefined, modifiers, SyntaxKind.ClassExpression); } function parseClassDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ClassDeclaration { diff --git a/src/compiler/symbolWalker.ts b/src/compiler/symbolWalker.ts index b03ef31db6e11..7f224c1dbf0d7 100644 --- a/src/compiler/symbolWalker.ts +++ b/src/compiler/symbolWalker.ts @@ -182,8 +182,10 @@ namespace ts { // query node on any of the symbol's declarations and get symbols there if ((d as any).type && (d as any).type.kind === SyntaxKind.TypeQuery) { const query = (d as any).type as TypeQueryNode; - const entity = getResolvedSymbol(getFirstIdentifier(query.exprName)); - visitSymbol(entity); + if (query.exprName.kind !== SyntaxKind.ClassExpression) { + const entity = getResolvedSymbol(getFirstIdentifier(query.exprName)); + visitSymbol(entity); + } } }); return false; diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 1fc500d2da81e..c7724f1566550 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -633,6 +633,7 @@ namespace ts { || isTypeAliasDeclaration(node) || isModuleDeclaration(node) || isClassDeclaration(node) + || isClassExpression(node) || isInterfaceDeclaration(node) || isFunctionLike(node) || isIndexSignatureDeclaration(node) @@ -849,7 +850,7 @@ namespace ts { getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing); } - if (isTypeQueryNode(input)) { + if (isTypeQueryNode(input) && input.exprName.kind !== SyntaxKind.ClassExpression) { checkEntityNameVisibility(input.exprName, enclosingDeclaration); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 34245a5e404a7..a2e4910fc44af 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1543,7 +1543,7 @@ namespace ts { export interface TypeQueryNode extends TypeNode { readonly kind: SyntaxKind.TypeQuery; - readonly exprName: EntityName; + readonly exprName: EntityName | ClassExpression; } // A TypeLiteral is the declaration node for an anonymous symbol. @@ -6804,8 +6804,8 @@ namespace ts { updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): FunctionTypeNode; createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode; updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): ConstructorTypeNode; - createTypeQueryNode(exprName: EntityName): TypeQueryNode; - updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode; + createTypeQueryNode(exprName: EntityName | ClassExpression): TypeQueryNode; + updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName | ClassExpression): TypeQueryNode; createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode; updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 6722e7ad5be1f..6b6cdb0345b00 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -1177,6 +1177,10 @@ namespace ts { || kind === SyntaxKind.Identifier; } + export function isEntityNameOrClassExpression(node: Node): node is EntityName { + return isEntityName(node) || node.kind === SyntaxKind.ClassExpression; + } + export function isPropertyName(node: Node): node is PropertyName { const kind = node.kind; return kind === SyntaxKind.Identifier diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index ad6e45f401184..6bbb3d46875f7 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -491,7 +491,7 @@ namespace ts { case SyntaxKind.TypeQuery: return factory.updateTypeQueryNode((node), - nodeVisitor((node).exprName, visitor, isEntityName)); + nodeVisitor((node).exprName, visitor, isEntityNameOrClassExpression)); case SyntaxKind.TypeLiteral: return factory.updateTypeLiteralNode((node), diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index b0282393cce6f..04c56085c3146 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -204,7 +204,7 @@ namespace ts { function getNodesToSearchForModifier(declaration: Node, modifierFlag: ModifierFlags): readonly Node[] | undefined { // Types of node whose children might have modifiers. - const container = declaration.parent as ModuleBlock | SourceFile | Block | CaseClause | DefaultClause | ConstructorDeclaration | MethodDeclaration | FunctionDeclaration | ObjectTypeDeclaration | ObjectLiteralExpression; + const container = declaration.parent; switch (container.kind) { case SyntaxKind.ModuleBlock: case SyntaxKind.SourceFile: @@ -216,22 +216,21 @@ namespace ts { return [...declaration.members, declaration]; } else { - return container.statements; + return (container).statements; } case SyntaxKind.Constructor: case SyntaxKind.MethodDeclaration: case SyntaxKind.FunctionDeclaration: - return [...container.parameters, ...(isClassLike(container.parent) ? container.parent.members : [])]; + return [...(container).parameters, ...(isClassLike(container.parent) ? container.parent.members : [])]; case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.TypeLiteral: - const nodes = container.members; - + const nodes = (container).members; // If we're an accessibility modifier, we're in an instance member and should search // the constructor's parameter list for instance members as well. if (modifierFlag & (ModifierFlags.AccessibilityModifier | ModifierFlags.Readonly)) { - const constructor = find(container.members, isConstructorDeclaration); + const constructor = find(nodes, isConstructorDeclaration); if (constructor) { return [...nodes, ...constructor.parameters]; } @@ -240,13 +239,11 @@ namespace ts { return [...nodes, container]; } return nodes; - - // Syntactically invalid positions that the parser might produce anyway - case SyntaxKind.ObjectLiteralExpression: - return undefined; - default: - Debug.assertNever(container, "Invalid container kind."); + if (modifierFlag & ModifierFlags.Abstract && isClassExpression(declaration)) { + return [...declaration.members, declaration]; + } + return undefined; } } diff --git a/src/services/refactors/extractType.ts b/src/services/refactors/extractType.ts index 7f528ae245d4f..0fcddf584ea2b 100644 --- a/src/services/refactors/extractType.ts +++ b/src/services/refactors/extractType.ts @@ -157,7 +157,7 @@ namespace ts.refactor { return true; } } - else if (isTypeQueryNode(node)) { + else if (isTypeQueryNode(node) && node.exprName.kind !== SyntaxKind.ClassExpression) { if (isIdentifier(node.exprName)) { const symbol = checker.resolveName(node.exprName.text, node.exprName, SymbolFlags.Value, /* excludeGlobals */ false); if (symbol && rangeContainsSkipTrivia(statement, symbol.valueDeclaration, file) && !rangeContainsSkipTrivia(selection, symbol.valueDeclaration, file)) { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ccc5d1fa1fc44..4de04b4b6c8c0 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -881,7 +881,7 @@ declare namespace ts { } export interface TypeQueryNode extends TypeNode { readonly kind: SyntaxKind.TypeQuery; - readonly exprName: EntityName; + readonly exprName: EntityName | ClassExpression; } export interface TypeLiteralNode extends TypeNode, Declaration { readonly kind: SyntaxKind.TypeLiteral; @@ -3235,8 +3235,8 @@ declare namespace ts { updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): FunctionTypeNode; createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode; updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): ConstructorTypeNode; - createTypeQueryNode(exprName: EntityName): TypeQueryNode; - updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode; + createTypeQueryNode(exprName: EntityName | ClassExpression): TypeQueryNode; + updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName | ClassExpression): TypeQueryNode; createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode; updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; @@ -4215,6 +4215,7 @@ declare namespace ts { function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken; function isModifier(node: Node): node is Modifier; function isEntityName(node: Node): node is EntityName; + function isEntityNameOrClassExpression(node: Node): node is EntityName; function isPropertyName(node: Node): node is PropertyName; function isBindingName(node: Node): node is BindingName; function isFunctionLike(node: Node): node is SignatureDeclaration; @@ -10184,9 +10185,9 @@ declare namespace ts { /** @deprecated Use `factory.updateConstructorTypeNode` or the factory supplied by your transformation context instead. */ const updateConstructorTypeNode: (node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode) => ConstructorTypeNode; /** @deprecated Use `factory.createTypeQueryNode` or the factory supplied by your transformation context instead. */ - const createTypeQueryNode: (exprName: EntityName) => TypeQueryNode; + const createTypeQueryNode: (exprName: Identifier | ClassExpression | QualifiedName) => TypeQueryNode; /** @deprecated Use `factory.updateTypeQueryNode` or the factory supplied by your transformation context instead. */ - const updateTypeQueryNode: (node: TypeQueryNode, exprName: EntityName) => TypeQueryNode; + const updateTypeQueryNode: (node: TypeQueryNode, exprName: Identifier | ClassExpression | QualifiedName) => TypeQueryNode; /** @deprecated Use `factory.createTypeLiteralNode` or the factory supplied by your transformation context instead. */ const createTypeLiteralNode: (members: readonly TypeElement[] | undefined) => TypeLiteralNode; /** @deprecated Use `factory.updateTypeLiteralNode` or the factory supplied by your transformation context instead. */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 440cebf6b0de6..c7cf93d24b6f3 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -881,7 +881,7 @@ declare namespace ts { } export interface TypeQueryNode extends TypeNode { readonly kind: SyntaxKind.TypeQuery; - readonly exprName: EntityName; + readonly exprName: EntityName | ClassExpression; } export interface TypeLiteralNode extends TypeNode, Declaration { readonly kind: SyntaxKind.TypeLiteral; @@ -3235,8 +3235,8 @@ declare namespace ts { updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): FunctionTypeNode; createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode; updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): ConstructorTypeNode; - createTypeQueryNode(exprName: EntityName): TypeQueryNode; - updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode; + createTypeQueryNode(exprName: EntityName | ClassExpression): TypeQueryNode; + updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName | ClassExpression): TypeQueryNode; createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode; updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; @@ -4215,6 +4215,7 @@ declare namespace ts { function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken; function isModifier(node: Node): node is Modifier; function isEntityName(node: Node): node is EntityName; + function isEntityNameOrClassExpression(node: Node): node is EntityName; function isPropertyName(node: Node): node is PropertyName; function isBindingName(node: Node): node is BindingName; function isFunctionLike(node: Node): node is SignatureDeclaration; @@ -6544,9 +6545,9 @@ declare namespace ts { /** @deprecated Use `factory.updateConstructorTypeNode` or the factory supplied by your transformation context instead. */ const updateConstructorTypeNode: (node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode) => ConstructorTypeNode; /** @deprecated Use `factory.createTypeQueryNode` or the factory supplied by your transformation context instead. */ - const createTypeQueryNode: (exprName: EntityName) => TypeQueryNode; + const createTypeQueryNode: (exprName: Identifier | ClassExpression | QualifiedName) => TypeQueryNode; /** @deprecated Use `factory.updateTypeQueryNode` or the factory supplied by your transformation context instead. */ - const updateTypeQueryNode: (node: TypeQueryNode, exprName: EntityName) => TypeQueryNode; + const updateTypeQueryNode: (node: TypeQueryNode, exprName: Identifier | ClassExpression | QualifiedName) => TypeQueryNode; /** @deprecated Use `factory.createTypeLiteralNode` or the factory supplied by your transformation context instead. */ const createTypeLiteralNode: (members: readonly TypeElement[] | undefined) => TypeLiteralNode; /** @deprecated Use `factory.updateTypeLiteralNode` or the factory supplied by your transformation context instead. */ diff --git a/tests/baselines/reference/jsdocTypeTag.js b/tests/baselines/reference/jsdocTypeTag.js index 394fb5a53da01..0e322e18141fc 100644 --- a/tests/baselines/reference/jsdocTypeTag.js +++ b/tests/baselines/reference/jsdocTypeTag.js @@ -66,6 +66,9 @@ var f; /** @type {new (s: string) => { s: string }} */ var ctor; + +/** @type {typeof class { s: string; static n: number }} */ +var ctor2; //// [b.ts] var S: string; @@ -90,6 +93,7 @@ var obj: any; var Func: Function; var f: (s: string) => number; var ctor: new (s: string) => { s: string }; +var ctor2: typeof class { s: string; static n: number }; //// [a.js] @@ -137,6 +141,8 @@ var Func; var f; /** @type {new (s: string) => { s: string }} */ var ctor; +/** @type {typeof class { s: string; static n: number }} */ +var ctor2; //// [b.js] var S; var s; @@ -160,3 +166,4 @@ var obj; var Func; var f; var ctor; +var ctor2; diff --git a/tests/baselines/reference/jsdocTypeTag.symbols b/tests/baselines/reference/jsdocTypeTag.symbols index 4aef9324eaa22..9a1a66417ddbf 100644 --- a/tests/baselines/reference/jsdocTypeTag.symbols +++ b/tests/baselines/reference/jsdocTypeTag.symbols @@ -87,6 +87,10 @@ var f; var ctor; >ctor : Symbol(ctor, Decl(a.js, 64, 3), Decl(b.ts, 21, 3)) +/** @type {typeof class { s: string; static n: number }} */ +var ctor2; +>ctor2 : Symbol(ctor2, Decl(a.js, 67, 3), Decl(b.ts, 22, 3)) + === tests/cases/conformance/jsdoc/b.ts === var S: string; >S : Symbol(S, Decl(a.js, 1, 3), Decl(b.ts, 0, 3)) @@ -160,3 +164,8 @@ var ctor: new (s: string) => { s: string }; >s : Symbol(s, Decl(b.ts, 21, 15)) >s : Symbol(s, Decl(b.ts, 21, 30)) +var ctor2: typeof class { s: string; static n: number }; +>ctor2 : Symbol(ctor2, Decl(a.js, 67, 3), Decl(b.ts, 22, 3)) +>s : Symbol((Anonymous class).s, Decl(b.ts, 22, 25)) +>n : Symbol((Anonymous class).n, Decl(b.ts, 22, 36)) + diff --git a/tests/baselines/reference/jsdocTypeTag.types b/tests/baselines/reference/jsdocTypeTag.types index 4ec4d2677aff2..01e44aa85293b 100644 --- a/tests/baselines/reference/jsdocTypeTag.types +++ b/tests/baselines/reference/jsdocTypeTag.types @@ -87,6 +87,10 @@ var f; var ctor; >ctor : new (s: string) => { s: string; } +/** @type {typeof class { s: string; static n: number }} */ +var ctor2; +>ctor2 : typeof (Anonymous class) + === tests/cases/conformance/jsdoc/b.ts === var S: string; >S : string @@ -160,3 +164,9 @@ var ctor: new (s: string) => { s: string }; >s : string >s : string +var ctor2: typeof class { s: string; static n: number }; +>ctor2 : typeof (Anonymous class) +>class { s: string; static n: number } : typeof (Anonymous class) +>s : string +>n : number + diff --git a/tests/baselines/reference/typeofClassExpression1.errors.txt b/tests/baselines/reference/typeofClassExpression1.errors.txt new file mode 100644 index 0000000000000..74ec0cf899eee --- /dev/null +++ b/tests/baselines/reference/typeofClassExpression1.errors.txt @@ -0,0 +1,125 @@ +tests/cases/conformance/types/specifyingTypes/typeQueries/typeofClassExpression1.ts(35,10): error TS2511: Cannot create an instance of an abstract class. + + +==== tests/cases/conformance/types/specifyingTypes/typeQueries/typeofClassExpression1.ts (1 errors) ==== + type TC1 = typeof class { + constructor(s: string); + static n: number; + s: string; + } + + declare let C1: TC1; + C1.n; + let c1 = new C1('hello'); + c1.s; + + declare let C2: typeof class { + constructor(s: string); + static n: number; + s: string; + } + C2.n; + let c2 = new C2('hello'); + c2.s; + + declare let C3: typeof class extends Error { + constructor(s: string); + static n: number; + } + C3.n; + let c3 = new C3('hello'); + c3.message; + + declare let C4: typeof abstract class { + constructor(s: string); + static n: number; + s: string; + } + C4.n; + let c4 = new C4('hello'); // Error + ~~~~~~~~~~~~~~~ +!!! error TS2511: Cannot create an instance of an abstract class. + + declare let C5: typeof class { + constructor(x: T); + x: T; + } + + let c51 = new C5('hello'); + c51.x; + let c52 = new C5(42); + c52.x; + + type BoxFactory = typeof class Box { + static default: T; + constructor(value?: T); + value: T; + } + + declare let StringBox: BoxFactory; + StringBox.default; + let sb = new StringBox('hello'); + sb.value; + + declare let NumberBox: BoxFactory; + NumberBox.default; + let nb = new NumberBox(42); + nb.value; + + declare const sb1: InstanceType>; + sb1.value; + + declare const nb1: InstanceType>; + nb1.value; + + function Printable1 object>(Base: T) { + return class extends Base { + static foo: string; + print() {} + } + } + + declare function Printable2 object>(Base: T): typeof class extends Base { + static foo: string; + print(): void; + }; + + type PrintableMixin = typeof class { + constructor(...args: any[]); // Indicates class is a mixin + static foo: string; + print(): void; + }; + + declare function Printable3 object, U>(Base: T): T & PrintableMixin; + + declare function Printable4 object>(Base: T): T & typeof class Printable { + constructor(...args: any[]); // Indicates class is a mixin + static foo: string; + print(): void; + }; + + class MyClass { + static bar: number; + x!: boolean; + } + + let PC1 = Printable1(MyClass); + let pc1 = new PC1(); + pc1.x; + pc1.print; + + let PC2 = Printable2(MyClass); + let pc2 = new PC2(); + pc2.x; + pc2.print; + + let PC3 = Printable3(MyClass); + let pc3 = new PC3(); + pc3.x; + pc3.print; + + let PC4 = Printable4(MyClass); + let pc4 = new PC4(); + pc4.x; + pc4.print; + \ No newline at end of file diff --git a/tests/baselines/reference/typeofClassExpression1.js b/tests/baselines/reference/typeofClassExpression1.js new file mode 100644 index 0000000000000..574d291b946b6 --- /dev/null +++ b/tests/baselines/reference/typeofClassExpression1.js @@ -0,0 +1,313 @@ +//// [typeofClassExpression1.ts] +type TC1 = typeof class { + constructor(s: string); + static n: number; + s: string; +} + +declare let C1: TC1; +C1.n; +let c1 = new C1('hello'); +c1.s; + +declare let C2: typeof class { + constructor(s: string); + static n: number; + s: string; +} +C2.n; +let c2 = new C2('hello'); +c2.s; + +declare let C3: typeof class extends Error { + constructor(s: string); + static n: number; +} +C3.n; +let c3 = new C3('hello'); +c3.message; + +declare let C4: typeof abstract class { + constructor(s: string); + static n: number; + s: string; +} +C4.n; +let c4 = new C4('hello'); // Error + +declare let C5: typeof class { + constructor(x: T); + x: T; +} + +let c51 = new C5('hello'); +c51.x; +let c52 = new C5(42); +c52.x; + +type BoxFactory = typeof class Box { + static default: T; + constructor(value?: T); + value: T; +} + +declare let StringBox: BoxFactory; +StringBox.default; +let sb = new StringBox('hello'); +sb.value; + +declare let NumberBox: BoxFactory; +NumberBox.default; +let nb = new NumberBox(42); +nb.value; + +declare const sb1: InstanceType>; +sb1.value; + +declare const nb1: InstanceType>; +nb1.value; + +function Printable1 object>(Base: T) { + return class extends Base { + static foo: string; + print() {} + } +} + +declare function Printable2 object>(Base: T): typeof class extends Base { + static foo: string; + print(): void; +}; + +type PrintableMixin = typeof class { + constructor(...args: any[]); // Indicates class is a mixin + static foo: string; + print(): void; +}; + +declare function Printable3 object, U>(Base: T): T & PrintableMixin; + +declare function Printable4 object>(Base: T): T & typeof class Printable { + constructor(...args: any[]); // Indicates class is a mixin + static foo: string; + print(): void; +}; + +class MyClass { + static bar: number; + x!: boolean; +} + +let PC1 = Printable1(MyClass); +let pc1 = new PC1(); +pc1.x; +pc1.print; + +let PC2 = Printable2(MyClass); +let pc2 = new PC2(); +pc2.x; +pc2.print; + +let PC3 = Printable3(MyClass); +let pc3 = new PC3(); +pc3.x; +pc3.print; + +let PC4 = Printable4(MyClass); +let pc4 = new PC4(); +pc4.x; +pc4.print; + + +//// [typeofClassExpression1.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +C1.n; +var c1 = new C1('hello'); +c1.s; +C2.n; +var c2 = new C2('hello'); +c2.s; +C3.n; +var c3 = new C3('hello'); +c3.message; +C4.n; +var c4 = new C4('hello'); // Error +var c51 = new C5('hello'); +c51.x; +var c52 = new C5(42); +c52.x; +StringBox["default"]; +var sb = new StringBox('hello'); +sb.value; +NumberBox["default"]; +var nb = new NumberBox(42); +nb.value; +sb1.value; +nb1.value; +function Printable1(Base) { + return /** @class */ (function (_super) { + __extends(class_1, _super); + function class_1() { + return _super !== null && _super.apply(this, arguments) || this; + } + class_1.prototype.print = function () { }; + return class_1; + }(Base)); +} +var MyClass = /** @class */ (function () { + function MyClass() { + } + return MyClass; +}()); +var PC1 = Printable1(MyClass); +var pc1 = new PC1(); +pc1.x; +pc1.print; +var PC2 = Printable2(MyClass); +var pc2 = new PC2(); +pc2.x; +pc2.print; +var PC3 = Printable3(MyClass); +var pc3 = new PC3(); +pc3.x; +pc3.print; +var PC4 = Printable4(MyClass); +var pc4 = new PC4(); +pc4.x; +pc4.print; + + +//// [typeofClassExpression1.d.ts] +declare type TC1 = typeof class { + constructor(s: string); + static n: number; + s: string; +}; +declare let C1: TC1; +declare let c1: { + s: string; +}; +declare let C2: typeof class { + constructor(s: string); + static n: number; + s: string; +}; +declare let c2: { + s: string; +}; +declare let C3: typeof class extends Error { + constructor(s: string); + static n: number; +}; +declare let c3: { + name: string; + message: string; + stack?: string | undefined; +}; +declare let C4: typeof abstract class { + constructor(s: string); + static n: number; + s: string; +}; +declare let c4: any; +declare let C5: typeof class { + constructor(x: T); + x: T; +}; +declare let c51: { + x: string; +}; +declare let c52: { + x: number; +}; +declare type BoxFactory = typeof class Box { + static default: T; + constructor(value?: T); + value: T; +}; +declare let StringBox: BoxFactory; +declare let sb: { + value: string; +}; +declare let NumberBox: BoxFactory; +declare let nb: { + value: number; +}; +declare const sb1: InstanceType>; +declare const nb1: InstanceType>; +declare function Printable1 object>(Base: T): { + new (...args: any[]): { + print(): void; + }; + foo: string; +} & T; +declare function Printable2 object>(Base: T): typeof class extends Base { + static foo: string; + print(): void; +}; +declare type PrintableMixin = typeof class { + constructor(...args: any[]); + static foo: string; + print(): void; +}; +declare function Printable3 object, U>(Base: T): T & PrintableMixin; +declare function Printable4 object>(Base: T): T & typeof class Printable { + constructor(...args: any[]); + static foo: string; + print(): void; +}; +declare class MyClass { + static bar: number; + x: boolean; +} +declare let PC1: { + new (...args: any[]): { + print(): void; + }; + foo: string; +} & typeof MyClass; +declare let pc1: { + print(): void; +} & MyClass; +declare let PC2: { + new (...args: any[]): { + print(): void; + }; + foo: string; +} & typeof MyClass; +declare let pc2: { + print(): void; +} & MyClass; +declare let PC3: typeof MyClass & { + new (...args: any[]): { + print(): void; + }; + foo: string; +}; +declare let pc3: MyClass & { + print(): void; +}; +declare let PC4: typeof MyClass & { + new (...args: any[]): { + print(): void; + }; + foo: string; +}; +declare let pc4: MyClass & { + print(): void; +}; diff --git a/tests/baselines/reference/typeofClassExpression1.symbols b/tests/baselines/reference/typeofClassExpression1.symbols new file mode 100644 index 0000000000000..11c0c9b48728a --- /dev/null +++ b/tests/baselines/reference/typeofClassExpression1.symbols @@ -0,0 +1,372 @@ +=== tests/cases/conformance/types/specifyingTypes/typeQueries/typeofClassExpression1.ts === +type TC1 = typeof class { +>TC1 : Symbol(TC1, Decl(typeofClassExpression1.ts, 0, 0)) + + constructor(s: string); +>s : Symbol(s, Decl(typeofClassExpression1.ts, 1, 16)) + + static n: number; +>n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 1, 27)) + + s: string; +>s : Symbol((Anonymous class).s, Decl(typeofClassExpression1.ts, 2, 21)) +} + +declare let C1: TC1; +>C1 : Symbol(C1, Decl(typeofClassExpression1.ts, 6, 11)) +>TC1 : Symbol(TC1, Decl(typeofClassExpression1.ts, 0, 0)) + +C1.n; +>C1.n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 1, 27)) +>C1 : Symbol(C1, Decl(typeofClassExpression1.ts, 6, 11)) +>n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 1, 27)) + +let c1 = new C1('hello'); +>c1 : Symbol(c1, Decl(typeofClassExpression1.ts, 8, 3)) +>C1 : Symbol(C1, Decl(typeofClassExpression1.ts, 6, 11)) + +c1.s; +>c1.s : Symbol((Anonymous class).s, Decl(typeofClassExpression1.ts, 2, 21)) +>c1 : Symbol(c1, Decl(typeofClassExpression1.ts, 8, 3)) +>s : Symbol((Anonymous class).s, Decl(typeofClassExpression1.ts, 2, 21)) + +declare let C2: typeof class { +>C2 : Symbol(C2, Decl(typeofClassExpression1.ts, 11, 11)) + + constructor(s: string); +>s : Symbol(s, Decl(typeofClassExpression1.ts, 12, 16)) + + static n: number; +>n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 12, 27)) + + s: string; +>s : Symbol((Anonymous class).s, Decl(typeofClassExpression1.ts, 13, 21)) +} +C2.n; +>C2.n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 12, 27)) +>C2 : Symbol(C2, Decl(typeofClassExpression1.ts, 11, 11)) +>n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 12, 27)) + +let c2 = new C2('hello'); +>c2 : Symbol(c2, Decl(typeofClassExpression1.ts, 17, 3)) +>C2 : Symbol(C2, Decl(typeofClassExpression1.ts, 11, 11)) + +c2.s; +>c2.s : Symbol((Anonymous class).s, Decl(typeofClassExpression1.ts, 13, 21)) +>c2 : Symbol(c2, Decl(typeofClassExpression1.ts, 17, 3)) +>s : Symbol((Anonymous class).s, Decl(typeofClassExpression1.ts, 13, 21)) + +declare let C3: typeof class extends Error { +>C3 : Symbol(C3, Decl(typeofClassExpression1.ts, 20, 11)) +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + constructor(s: string); +>s : Symbol(s, Decl(typeofClassExpression1.ts, 21, 16)) + + static n: number; +>n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 21, 27)) +} +C3.n; +>C3.n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 21, 27)) +>C3 : Symbol(C3, Decl(typeofClassExpression1.ts, 20, 11)) +>n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 21, 27)) + +let c3 = new C3('hello'); +>c3 : Symbol(c3, Decl(typeofClassExpression1.ts, 25, 3)) +>C3 : Symbol(C3, Decl(typeofClassExpression1.ts, 20, 11)) + +c3.message; +>c3.message : Symbol(Error.message, Decl(lib.es5.d.ts, --, --)) +>c3 : Symbol(c3, Decl(typeofClassExpression1.ts, 25, 3)) +>message : Symbol(Error.message, Decl(lib.es5.d.ts, --, --)) + +declare let C4: typeof abstract class { +>C4 : Symbol(C4, Decl(typeofClassExpression1.ts, 28, 11)) + + constructor(s: string); +>s : Symbol(s, Decl(typeofClassExpression1.ts, 29, 16)) + + static n: number; +>n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 29, 27)) + + s: string; +>s : Symbol((Anonymous class).s, Decl(typeofClassExpression1.ts, 30, 21)) +} +C4.n; +>C4.n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 29, 27)) +>C4 : Symbol(C4, Decl(typeofClassExpression1.ts, 28, 11)) +>n : Symbol((Anonymous class).n, Decl(typeofClassExpression1.ts, 29, 27)) + +let c4 = new C4('hello'); // Error +>c4 : Symbol(c4, Decl(typeofClassExpression1.ts, 34, 3)) +>C4 : Symbol(C4, Decl(typeofClassExpression1.ts, 28, 11)) + +declare let C5: typeof class { +>C5 : Symbol(C5, Decl(typeofClassExpression1.ts, 36, 11)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 36, 29)) + + constructor(x: T); +>x : Symbol(x, Decl(typeofClassExpression1.ts, 37, 16)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 36, 29)) + + x: T; +>x : Symbol((Anonymous class).x, Decl(typeofClassExpression1.ts, 37, 22)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 36, 29)) +} + +let c51 = new C5('hello'); +>c51 : Symbol(c51, Decl(typeofClassExpression1.ts, 41, 3)) +>C5 : Symbol(C5, Decl(typeofClassExpression1.ts, 36, 11)) + +c51.x; +>c51.x : Symbol((Anonymous class).x, Decl(typeofClassExpression1.ts, 37, 22)) +>c51 : Symbol(c51, Decl(typeofClassExpression1.ts, 41, 3)) +>x : Symbol((Anonymous class).x, Decl(typeofClassExpression1.ts, 37, 22)) + +let c52 = new C5(42); +>c52 : Symbol(c52, Decl(typeofClassExpression1.ts, 43, 3)) +>C5 : Symbol(C5, Decl(typeofClassExpression1.ts, 36, 11)) + +c52.x; +>c52.x : Symbol((Anonymous class).x, Decl(typeofClassExpression1.ts, 37, 22)) +>c52 : Symbol(c52, Decl(typeofClassExpression1.ts, 43, 3)) +>x : Symbol((Anonymous class).x, Decl(typeofClassExpression1.ts, 37, 22)) + +type BoxFactory = typeof class Box { +>BoxFactory : Symbol(BoxFactory, Decl(typeofClassExpression1.ts, 44, 6)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 46, 16)) +>Box : Symbol(Box, Decl(typeofClassExpression1.ts, 46, 27)) + + static default: T; +>default : Symbol(Box.default, Decl(typeofClassExpression1.ts, 46, 39)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 46, 16)) + + constructor(value?: T); +>value : Symbol(value, Decl(typeofClassExpression1.ts, 48, 16)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 46, 16)) + + value: T; +>value : Symbol(Box.value, Decl(typeofClassExpression1.ts, 48, 27)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 46, 16)) +} + +declare let StringBox: BoxFactory; +>StringBox : Symbol(StringBox, Decl(typeofClassExpression1.ts, 52, 11)) +>BoxFactory : Symbol(BoxFactory, Decl(typeofClassExpression1.ts, 44, 6)) + +StringBox.default; +>StringBox.default : Symbol(Box.default, Decl(typeofClassExpression1.ts, 46, 39)) +>StringBox : Symbol(StringBox, Decl(typeofClassExpression1.ts, 52, 11)) +>default : Symbol(Box.default, Decl(typeofClassExpression1.ts, 46, 39)) + +let sb = new StringBox('hello'); +>sb : Symbol(sb, Decl(typeofClassExpression1.ts, 54, 3)) +>StringBox : Symbol(StringBox, Decl(typeofClassExpression1.ts, 52, 11)) + +sb.value; +>sb.value : Symbol(Box.value, Decl(typeofClassExpression1.ts, 48, 27)) +>sb : Symbol(sb, Decl(typeofClassExpression1.ts, 54, 3)) +>value : Symbol(Box.value, Decl(typeofClassExpression1.ts, 48, 27)) + +declare let NumberBox: BoxFactory; +>NumberBox : Symbol(NumberBox, Decl(typeofClassExpression1.ts, 57, 11)) +>BoxFactory : Symbol(BoxFactory, Decl(typeofClassExpression1.ts, 44, 6)) + +NumberBox.default; +>NumberBox.default : Symbol(Box.default, Decl(typeofClassExpression1.ts, 46, 39)) +>NumberBox : Symbol(NumberBox, Decl(typeofClassExpression1.ts, 57, 11)) +>default : Symbol(Box.default, Decl(typeofClassExpression1.ts, 46, 39)) + +let nb = new NumberBox(42); +>nb : Symbol(nb, Decl(typeofClassExpression1.ts, 59, 3)) +>NumberBox : Symbol(NumberBox, Decl(typeofClassExpression1.ts, 57, 11)) + +nb.value; +>nb.value : Symbol(Box.value, Decl(typeofClassExpression1.ts, 48, 27)) +>nb : Symbol(nb, Decl(typeofClassExpression1.ts, 59, 3)) +>value : Symbol(Box.value, Decl(typeofClassExpression1.ts, 48, 27)) + +declare const sb1: InstanceType>; +>sb1 : Symbol(sb1, Decl(typeofClassExpression1.ts, 62, 13)) +>InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --)) +>BoxFactory : Symbol(BoxFactory, Decl(typeofClassExpression1.ts, 44, 6)) + +sb1.value; +>sb1.value : Symbol(Box.value, Decl(typeofClassExpression1.ts, 48, 27)) +>sb1 : Symbol(sb1, Decl(typeofClassExpression1.ts, 62, 13)) +>value : Symbol(Box.value, Decl(typeofClassExpression1.ts, 48, 27)) + +declare const nb1: InstanceType>; +>nb1 : Symbol(nb1, Decl(typeofClassExpression1.ts, 65, 13)) +>InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --)) +>BoxFactory : Symbol(BoxFactory, Decl(typeofClassExpression1.ts, 44, 6)) + +nb1.value; +>nb1.value : Symbol(Box.value, Decl(typeofClassExpression1.ts, 48, 27)) +>nb1 : Symbol(nb1, Decl(typeofClassExpression1.ts, 65, 13)) +>value : Symbol(Box.value, Decl(typeofClassExpression1.ts, 48, 27)) + +function Printable1 object>(Base: T) { +>Printable1 : Symbol(Printable1, Decl(typeofClassExpression1.ts, 66, 10)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 68, 20)) +>args : Symbol(args, Decl(typeofClassExpression1.ts, 68, 35)) +>Base : Symbol(Base, Decl(typeofClassExpression1.ts, 68, 62)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 68, 20)) + + return class extends Base { +>Base : Symbol(Base, Decl(typeofClassExpression1.ts, 68, 62)) + + static foo: string; +>foo : Symbol((Anonymous class).foo, Decl(typeofClassExpression1.ts, 69, 31)) + + print() {} +>print : Symbol((Anonymous class).print, Decl(typeofClassExpression1.ts, 70, 27)) + } +} + +declare function Printable2 object>(Base: T): typeof class extends Base { +>Printable2 : Symbol(Printable2, Decl(typeofClassExpression1.ts, 73, 1)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 75, 28)) +>args : Symbol(args, Decl(typeofClassExpression1.ts, 75, 43)) +>Base : Symbol(Base, Decl(typeofClassExpression1.ts, 75, 70)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 75, 28)) +>Base : Symbol(Base, Decl(typeofClassExpression1.ts, 75, 70)) + + static foo: string; +>foo : Symbol((Anonymous class).foo, Decl(typeofClassExpression1.ts, 75, 107)) + + print(): void; +>print : Symbol((Anonymous class).print, Decl(typeofClassExpression1.ts, 76, 23)) + +}; + +type PrintableMixin = typeof class { +>PrintableMixin : Symbol(PrintableMixin, Decl(typeofClassExpression1.ts, 78, 2)) + + constructor(...args: any[]); // Indicates class is a mixin +>args : Symbol(args, Decl(typeofClassExpression1.ts, 81, 16)) + + static foo: string; +>foo : Symbol((Anonymous class).foo, Decl(typeofClassExpression1.ts, 81, 32)) + + print(): void; +>print : Symbol((Anonymous class).print, Decl(typeofClassExpression1.ts, 82, 23)) + +}; + +declare function Printable3 object, U>(Base: T): T & PrintableMixin; +>Printable3 : Symbol(Printable3, Decl(typeofClassExpression1.ts, 84, 2)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 86, 28)) +>args : Symbol(args, Decl(typeofClassExpression1.ts, 86, 43)) +>U : Symbol(U, Decl(typeofClassExpression1.ts, 86, 69)) +>Base : Symbol(Base, Decl(typeofClassExpression1.ts, 86, 73)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 86, 28)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 86, 28)) +>PrintableMixin : Symbol(PrintableMixin, Decl(typeofClassExpression1.ts, 78, 2)) + +declare function Printable4 object>(Base: T): T & typeof class Printable { +>Printable4 : Symbol(Printable4, Decl(typeofClassExpression1.ts, 86, 102)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 88, 28)) +>args : Symbol(args, Decl(typeofClassExpression1.ts, 88, 43)) +>Base : Symbol(Base, Decl(typeofClassExpression1.ts, 88, 70)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 88, 28)) +>T : Symbol(T, Decl(typeofClassExpression1.ts, 88, 28)) +>Printable : Symbol(Printable, Decl(typeofClassExpression1.ts, 88, 90)) + + constructor(...args: any[]); // Indicates class is a mixin +>args : Symbol(args, Decl(typeofClassExpression1.ts, 89, 16)) + + static foo: string; +>foo : Symbol(Printable.foo, Decl(typeofClassExpression1.ts, 89, 32)) + + print(): void; +>print : Symbol(Printable.print, Decl(typeofClassExpression1.ts, 90, 23)) + +}; + +class MyClass { +>MyClass : Symbol(MyClass, Decl(typeofClassExpression1.ts, 92, 2)) + + static bar: number; +>bar : Symbol(MyClass.bar, Decl(typeofClassExpression1.ts, 94, 15)) + + x!: boolean; +>x : Symbol(MyClass.x, Decl(typeofClassExpression1.ts, 95, 23)) +} + +let PC1 = Printable1(MyClass); +>PC1 : Symbol(PC1, Decl(typeofClassExpression1.ts, 99, 3)) +>Printable1 : Symbol(Printable1, Decl(typeofClassExpression1.ts, 66, 10)) +>MyClass : Symbol(MyClass, Decl(typeofClassExpression1.ts, 92, 2)) + +let pc1 = new PC1(); +>pc1 : Symbol(pc1, Decl(typeofClassExpression1.ts, 100, 3)) +>PC1 : Symbol(PC1, Decl(typeofClassExpression1.ts, 99, 3)) + +pc1.x; +>pc1.x : Symbol(MyClass.x, Decl(typeofClassExpression1.ts, 95, 23)) +>pc1 : Symbol(pc1, Decl(typeofClassExpression1.ts, 100, 3)) +>x : Symbol(MyClass.x, Decl(typeofClassExpression1.ts, 95, 23)) + +pc1.print; +>pc1.print : Symbol((Anonymous class).print, Decl(typeofClassExpression1.ts, 70, 27)) +>pc1 : Symbol(pc1, Decl(typeofClassExpression1.ts, 100, 3)) +>print : Symbol((Anonymous class).print, Decl(typeofClassExpression1.ts, 70, 27)) + +let PC2 = Printable2(MyClass); +>PC2 : Symbol(PC2, Decl(typeofClassExpression1.ts, 104, 3)) +>Printable2 : Symbol(Printable2, Decl(typeofClassExpression1.ts, 73, 1)) +>MyClass : Symbol(MyClass, Decl(typeofClassExpression1.ts, 92, 2)) + +let pc2 = new PC2(); +>pc2 : Symbol(pc2, Decl(typeofClassExpression1.ts, 105, 3)) +>PC2 : Symbol(PC2, Decl(typeofClassExpression1.ts, 104, 3)) + +pc2.x; +>pc2.x : Symbol(MyClass.x, Decl(typeofClassExpression1.ts, 95, 23)) +>pc2 : Symbol(pc2, Decl(typeofClassExpression1.ts, 105, 3)) +>x : Symbol(MyClass.x, Decl(typeofClassExpression1.ts, 95, 23)) + +pc2.print; +>pc2.print : Symbol((Anonymous class).print, Decl(typeofClassExpression1.ts, 76, 23)) +>pc2 : Symbol(pc2, Decl(typeofClassExpression1.ts, 105, 3)) +>print : Symbol((Anonymous class).print, Decl(typeofClassExpression1.ts, 76, 23)) + +let PC3 = Printable3(MyClass); +>PC3 : Symbol(PC3, Decl(typeofClassExpression1.ts, 109, 3)) +>Printable3 : Symbol(Printable3, Decl(typeofClassExpression1.ts, 84, 2)) +>MyClass : Symbol(MyClass, Decl(typeofClassExpression1.ts, 92, 2)) + +let pc3 = new PC3(); +>pc3 : Symbol(pc3, Decl(typeofClassExpression1.ts, 110, 3)) +>PC3 : Symbol(PC3, Decl(typeofClassExpression1.ts, 109, 3)) + +pc3.x; +>pc3.x : Symbol(MyClass.x, Decl(typeofClassExpression1.ts, 95, 23)) +>pc3 : Symbol(pc3, Decl(typeofClassExpression1.ts, 110, 3)) +>x : Symbol(MyClass.x, Decl(typeofClassExpression1.ts, 95, 23)) + +pc3.print; +>pc3.print : Symbol((Anonymous class).print, Decl(typeofClassExpression1.ts, 82, 23)) +>pc3 : Symbol(pc3, Decl(typeofClassExpression1.ts, 110, 3)) +>print : Symbol((Anonymous class).print, Decl(typeofClassExpression1.ts, 82, 23)) + +let PC4 = Printable4(MyClass); +>PC4 : Symbol(PC4, Decl(typeofClassExpression1.ts, 114, 3)) +>Printable4 : Symbol(Printable4, Decl(typeofClassExpression1.ts, 86, 102)) +>MyClass : Symbol(MyClass, Decl(typeofClassExpression1.ts, 92, 2)) + +let pc4 = new PC4(); +>pc4 : Symbol(pc4, Decl(typeofClassExpression1.ts, 115, 3)) +>PC4 : Symbol(PC4, Decl(typeofClassExpression1.ts, 114, 3)) + +pc4.x; +>pc4.x : Symbol(MyClass.x, Decl(typeofClassExpression1.ts, 95, 23)) +>pc4 : Symbol(pc4, Decl(typeofClassExpression1.ts, 115, 3)) +>x : Symbol(MyClass.x, Decl(typeofClassExpression1.ts, 95, 23)) + +pc4.print; +>pc4.print : Symbol(Printable.print, Decl(typeofClassExpression1.ts, 90, 23)) +>pc4 : Symbol(pc4, Decl(typeofClassExpression1.ts, 115, 3)) +>print : Symbol(Printable.print, Decl(typeofClassExpression1.ts, 90, 23)) + diff --git a/tests/baselines/reference/typeofClassExpression1.types b/tests/baselines/reference/typeofClassExpression1.types new file mode 100644 index 0000000000000..25d9db6d4ff1e --- /dev/null +++ b/tests/baselines/reference/typeofClassExpression1.types @@ -0,0 +1,380 @@ +=== tests/cases/conformance/types/specifyingTypes/typeQueries/typeofClassExpression1.ts === +type TC1 = typeof class { +>TC1 : typeof (Anonymous class) +>class { constructor(s: string); static n: number; s: string;} : typeof (Anonymous class) + + constructor(s: string); +>s : string + + static n: number; +>n : number + + s: string; +>s : string +} + +declare let C1: TC1; +>C1 : typeof (Anonymous class) + +C1.n; +>C1.n : number +>C1 : typeof (Anonymous class) +>n : number + +let c1 = new C1('hello'); +>c1 : (Anonymous class) +>new C1('hello') : (Anonymous class) +>C1 : typeof (Anonymous class) +>'hello' : "hello" + +c1.s; +>c1.s : string +>c1 : (Anonymous class) +>s : string + +declare let C2: typeof class { +>C2 : typeof (Anonymous class) +>class { constructor(s: string); static n: number; s: string;} : typeof (Anonymous class) + + constructor(s: string); +>s : string + + static n: number; +>n : number + + s: string; +>s : string +} +C2.n; +>C2.n : number +>C2 : typeof (Anonymous class) +>n : number + +let c2 = new C2('hello'); +>c2 : (Anonymous class) +>new C2('hello') : (Anonymous class) +>C2 : typeof (Anonymous class) +>'hello' : "hello" + +c2.s; +>c2.s : string +>c2 : (Anonymous class) +>s : string + +declare let C3: typeof class extends Error { +>C3 : typeof (Anonymous class) +>class extends Error { constructor(s: string); static n: number;} : typeof (Anonymous class) +>Error : Error + + constructor(s: string); +>s : string + + static n: number; +>n : number +} +C3.n; +>C3.n : number +>C3 : typeof (Anonymous class) +>n : number + +let c3 = new C3('hello'); +>c3 : (Anonymous class) +>new C3('hello') : (Anonymous class) +>C3 : typeof (Anonymous class) +>'hello' : "hello" + +c3.message; +>c3.message : string +>c3 : (Anonymous class) +>message : string + +declare let C4: typeof abstract class { +>C4 : typeof (Anonymous class) +>abstract class { constructor(s: string); static n: number; s: string;} : typeof (Anonymous class) + + constructor(s: string); +>s : string + + static n: number; +>n : number + + s: string; +>s : string +} +C4.n; +>C4.n : number +>C4 : typeof (Anonymous class) +>n : number + +let c4 = new C4('hello'); // Error +>c4 : any +>new C4('hello') : any +>C4 : typeof (Anonymous class) +>'hello' : "hello" + +declare let C5: typeof class { +>C5 : typeof (Anonymous class) +>class { constructor(x: T); x: T;} : typeof (Anonymous class) + + constructor(x: T); +>x : T + + x: T; +>x : T +} + +let c51 = new C5('hello'); +>c51 : (Anonymous class) +>new C5('hello') : (Anonymous class) +>C5 : typeof (Anonymous class) +>'hello' : "hello" + +c51.x; +>c51.x : string +>c51 : (Anonymous class) +>x : string + +let c52 = new C5(42); +>c52 : (Anonymous class) +>new C5(42) : (Anonymous class) +>C5 : typeof (Anonymous class) +>42 : 42 + +c52.x; +>c52.x : number +>c52 : (Anonymous class) +>x : number + +type BoxFactory = typeof class Box { +>BoxFactory : typeof Box +>class Box { static default: T; constructor(value?: T); value: T;} : typeof Box +>Box : typeof Box + + static default: T; +>default : T + + constructor(value?: T); +>value : T | undefined + + value: T; +>value : T +} + +declare let StringBox: BoxFactory; +>StringBox : typeof Box + +StringBox.default; +>StringBox.default : string +>StringBox : typeof Box +>default : string + +let sb = new StringBox('hello'); +>sb : BoxFactory.Box +>new StringBox('hello') : BoxFactory.Box +>StringBox : typeof Box +>'hello' : "hello" + +sb.value; +>sb.value : string +>sb : BoxFactory.Box +>value : string + +declare let NumberBox: BoxFactory; +>NumberBox : typeof Box + +NumberBox.default; +>NumberBox.default : number +>NumberBox : typeof Box +>default : number + +let nb = new NumberBox(42); +>nb : BoxFactory.Box +>new NumberBox(42) : BoxFactory.Box +>NumberBox : typeof Box +>42 : 42 + +nb.value; +>nb.value : number +>nb : BoxFactory.Box +>value : number + +declare const sb1: InstanceType>; +>sb1 : BoxFactory.Box + +sb1.value; +>sb1.value : string +>sb1 : BoxFactory.Box +>value : string + +declare const nb1: InstanceType>; +>nb1 : BoxFactory.Box + +nb1.value; +>nb1.value : number +>nb1 : BoxFactory.Box +>value : number + +function Printable1 object>(Base: T) { +>Printable1 : object>(Base: T) => { new (...args: any[]): (Anonymous class); prototype: Printable1.(Anonymous class); foo: string; } & T +>args : any[] +>Base : T + + return class extends Base { +>class extends Base { static foo: string; print() {} } : { new (...args: any[]): (Anonymous class); prototype: Printable1.(Anonymous class); foo: string; } & T +>Base : object + + static foo: string; +>foo : string + + print() {} +>print : () => void + } +} + +declare function Printable2 object>(Base: T): typeof class extends Base { +>Printable2 : object>(Base: T) => typeof class extends Base { static foo: string; print(): void;} +>args : any[] +>Base : T +>class extends Base { static foo: string; print(): void;} : { new (...args: any[]): (Anonymous class); prototype: Printable2.(Anonymous class); foo: string; } & T +>Base : object + + static foo: string; +>foo : string + + print(): void; +>print : () => void + +}; + +type PrintableMixin = typeof class { +>PrintableMixin : typeof (Anonymous class) +>class { constructor(...args: any[]); // Indicates class is a mixin static foo: string; print(): void;} : typeof (Anonymous class) + + constructor(...args: any[]); // Indicates class is a mixin +>args : any[] + + static foo: string; +>foo : string + + print(): void; +>print : () => void + +}; + +declare function Printable3 object, U>(Base: T): T & PrintableMixin; +>Printable3 : object, U>(Base: T) => T & PrintableMixin +>args : any[] +>Base : T + +declare function Printable4 object>(Base: T): T & typeof class Printable { +>Printable4 : object>(Base: T) => T & typeof Printable +>args : any[] +>Base : T +>class Printable { constructor(...args: any[]); // Indicates class is a mixin static foo: string; print(): void;} : typeof Printable +>Printable : typeof Printable + + constructor(...args: any[]); // Indicates class is a mixin +>args : any[] + + static foo: string; +>foo : string + + print(): void; +>print : () => void + +}; + +class MyClass { +>MyClass : MyClass + + static bar: number; +>bar : number + + x!: boolean; +>x : boolean +} + +let PC1 = Printable1(MyClass); +>PC1 : { new (...args: any[]): Printable1.(Anonymous class); prototype: Printable1.(Anonymous class); foo: string; } & typeof MyClass +>Printable1(MyClass) : { new (...args: any[]): Printable1.(Anonymous class); prototype: Printable1.(Anonymous class); foo: string; } & typeof MyClass +>Printable1 : object>(Base: T) => { new (...args: any[]): (Anonymous class); prototype: Printable1.(Anonymous class); foo: string; } & T +>MyClass : typeof MyClass + +let pc1 = new PC1(); +>pc1 : Printable1.(Anonymous class) & MyClass +>new PC1() : Printable1.(Anonymous class) & MyClass +>PC1 : { new (...args: any[]): Printable1.(Anonymous class); prototype: Printable1.(Anonymous class); foo: string; } & typeof MyClass + +pc1.x; +>pc1.x : boolean +>pc1 : Printable1.(Anonymous class) & MyClass +>x : boolean + +pc1.print; +>pc1.print : () => void +>pc1 : Printable1.(Anonymous class) & MyClass +>print : () => void + +let PC2 = Printable2(MyClass); +>PC2 : { new (...args: any[]): Printable2.(Anonymous class); prototype: Printable2.(Anonymous class); foo: string; } & typeof MyClass +>Printable2(MyClass) : { new (...args: any[]): Printable2.(Anonymous class); prototype: Printable2.(Anonymous class); foo: string; } & typeof MyClass +>Printable2 : object>(Base: T) => { new (...args: any[]): (Anonymous class); prototype: Printable2.(Anonymous class); foo: string; } & T +>MyClass : typeof MyClass + +let pc2 = new PC2(); +>pc2 : Printable2.(Anonymous class) & MyClass +>new PC2() : Printable2.(Anonymous class) & MyClass +>PC2 : { new (...args: any[]): Printable2.(Anonymous class); prototype: Printable2.(Anonymous class); foo: string; } & typeof MyClass + +pc2.x; +>pc2.x : boolean +>pc2 : Printable2.(Anonymous class) & MyClass +>x : boolean + +pc2.print; +>pc2.print : () => void +>pc2 : Printable2.(Anonymous class) & MyClass +>print : () => void + +let PC3 = Printable3(MyClass); +>PC3 : typeof MyClass & typeof (Anonymous class) +>Printable3(MyClass) : typeof MyClass & typeof (Anonymous class) +>Printable3 : object, U>(Base: T) => T & typeof (Anonymous class) +>MyClass : typeof MyClass + +let pc3 = new PC3(); +>pc3 : MyClass & (Anonymous class) +>new PC3() : MyClass & (Anonymous class) +>PC3 : typeof MyClass & typeof (Anonymous class) + +pc3.x; +>pc3.x : boolean +>pc3 : MyClass & (Anonymous class) +>x : boolean + +pc3.print; +>pc3.print : () => void +>pc3 : MyClass & (Anonymous class) +>print : () => void + +let PC4 = Printable4(MyClass); +>PC4 : typeof MyClass & typeof Printable +>Printable4(MyClass) : typeof MyClass & typeof Printable +>Printable4 : object>(Base: T) => T & typeof Printable +>MyClass : typeof MyClass + +let pc4 = new PC4(); +>pc4 : MyClass & Printable4.Printable +>new PC4() : MyClass & Printable4.Printable +>PC4 : typeof MyClass & typeof Printable + +pc4.x; +>pc4.x : boolean +>pc4 : MyClass & Printable4.Printable +>x : boolean + +pc4.print; +>pc4.print : () => void +>pc4 : MyClass & Printable4.Printable +>print : () => void + diff --git a/tests/cases/conformance/jsdoc/jsdocTypeTag.ts b/tests/cases/conformance/jsdoc/jsdocTypeTag.ts index b5fdd397fa765..5a116a620e7f8 100644 --- a/tests/cases/conformance/jsdoc/jsdocTypeTag.ts +++ b/tests/cases/conformance/jsdoc/jsdocTypeTag.ts @@ -69,6 +69,9 @@ var f; /** @type {new (s: string) => { s: string }} */ var ctor; +/** @type {typeof class { s: string; static n: number }} */ +var ctor2; + // @filename: b.ts var S: string; var s: string; @@ -92,3 +95,4 @@ var obj: any; var Func: Function; var f: (s: string) => number; var ctor: new (s: string) => { s: string }; +var ctor2: typeof class { s: string; static n: number }; diff --git a/tests/cases/conformance/types/specifyingTypes/typeQueries/typeofClassExpression1.ts b/tests/cases/conformance/types/specifyingTypes/typeQueries/typeofClassExpression1.ts new file mode 100644 index 0000000000000..86f236927fcbd --- /dev/null +++ b/tests/cases/conformance/types/specifyingTypes/typeQueries/typeofClassExpression1.ts @@ -0,0 +1,121 @@ +// @strict: true +// @declaration: true + +type TC1 = typeof class { + constructor(s: string); + static n: number; + s: string; +} + +declare let C1: TC1; +C1.n; +let c1 = new C1('hello'); +c1.s; + +declare let C2: typeof class { + constructor(s: string); + static n: number; + s: string; +} +C2.n; +let c2 = new C2('hello'); +c2.s; + +declare let C3: typeof class extends Error { + constructor(s: string); + static n: number; +} +C3.n; +let c3 = new C3('hello'); +c3.message; + +declare let C4: typeof abstract class { + constructor(s: string); + static n: number; + s: string; +} +C4.n; +let c4 = new C4('hello'); // Error + +declare let C5: typeof class { + constructor(x: T); + x: T; +} + +let c51 = new C5('hello'); +c51.x; +let c52 = new C5(42); +c52.x; + +type BoxFactory = typeof class Box { + static default: T; + constructor(value?: T); + value: T; +} + +declare let StringBox: BoxFactory; +StringBox.default; +let sb = new StringBox('hello'); +sb.value; + +declare let NumberBox: BoxFactory; +NumberBox.default; +let nb = new NumberBox(42); +nb.value; + +declare const sb1: InstanceType>; +sb1.value; + +declare const nb1: InstanceType>; +nb1.value; + +function Printable1 object>(Base: T) { + return class extends Base { + static foo: string; + print() {} + } +} + +declare function Printable2 object>(Base: T): typeof class extends Base { + static foo: string; + print(): void; +}; + +type PrintableMixin = typeof class { + constructor(...args: any[]); // Indicates class is a mixin + static foo: string; + print(): void; +}; + +declare function Printable3 object, U>(Base: T): T & PrintableMixin; + +declare function Printable4 object>(Base: T): T & typeof class Printable { + constructor(...args: any[]); // Indicates class is a mixin + static foo: string; + print(): void; +}; + +class MyClass { + static bar: number; + x!: boolean; +} + +let PC1 = Printable1(MyClass); +let pc1 = new PC1(); +pc1.x; +pc1.print; + +let PC2 = Printable2(MyClass); +let pc2 = new PC2(); +pc2.x; +pc2.print; + +let PC3 = Printable3(MyClass); +let pc3 = new PC3(); +pc3.x; +pc3.print; + +let PC4 = Printable4(MyClass); +let pc4 = new PC4(); +pc4.x; +pc4.print; diff --git a/tests/cases/fourslash/getOccurrencesAbstract02.ts b/tests/cases/fourslash/getOccurrencesAbstract02.ts index 1decdaaf69ce4..b2b56b3038172 100644 --- a/tests/cases/fourslash/getOccurrencesAbstract02.ts +++ b/tests/cases/fourslash/getOccurrencesAbstract02.ts @@ -5,7 +5,7 @@ //// [|abstract|] walk(): void; //// [|abstract|] makeSound(): void; ////} -////// abstract cannot appear here, won't get highlighted +////// abstract can appear on class expressions ////let c = /*1*/abstract class Foo { //// /*2*/abstract foo(): void; //// abstract bar(): void; @@ -14,7 +14,7 @@ verify.rangesAreOccurrences(false); goTo.marker("1"); -verify.occurrencesAtPositionCount(0); +verify.occurrencesAtPositionCount(3); goTo.marker("2"); -verify.occurrencesAtPositionCount(2); +verify.occurrencesAtPositionCount(3);