Skip to content

Commit

Permalink
Support TypeScript 4.2 abstract constructor signatures (#12628)
Browse files Browse the repository at this point in the history
Co-authored-by: Huáng Jùnliàng <jlhwung@gmail.com>
Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
  • Loading branch information
3 people committed Feb 21, 2021
1 parent 74dc70a commit e4588be
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 5 deletions.
4 changes: 4 additions & 0 deletions packages/babel-generator/src/generators/typescript.ts
Expand Up @@ -194,6 +194,10 @@ export function TSFunctionType(this: Printer, node: t.TSFunctionType) {
}

export function TSConstructorType(this: Printer, node: t.TSConstructorType) {
if (node.abstract) {
this.word("abstract");
this.space();
}
this.word("new");
this.space();
this.tsPrintFunctionOrConstructorType(node);
Expand Down
@@ -0,0 +1 @@
const x: abstract new () => void;
@@ -0,0 +1 @@
const x: abstract new () => void;
@@ -0,0 +1 @@
const x: new () => void;
@@ -0,0 +1 @@
const x: new () => void;
16 changes: 15 additions & 1 deletion packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -790,10 +790,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>

tsParseFunctionOrConstructorType(
type: "TSFunctionType" | "TSConstructorType",
abstract?: boolean,
): N.TsFunctionOrConstructorType {
const node: N.TsFunctionOrConstructorType = this.startNode();
if (type === "TSConstructorType") {
this.expect(tt._new);
// $FlowIgnore
node.abstract = !!abstract;
if (abstract) this.next();
this.next(); // eat `new`
}
this.tsFillSignature(tt.arrow, node);
return this.finishNode(node, type);
Expand Down Expand Up @@ -1219,13 +1223,23 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishNode(node, "TSConditionalType");
}

isAbstractConstructorSignature(): boolean {
return this.isContextual("abstract") && this.lookahead().type === tt._new;
}

tsParseNonConditionalType(): N.TsType {
if (this.tsIsStartOfFunctionType()) {
return this.tsParseFunctionOrConstructorType("TSFunctionType");
}
if (this.match(tt._new)) {
// As in `new () => Date`
return this.tsParseFunctionOrConstructorType("TSConstructorType");
} else if (this.isAbstractConstructorSignature()) {
// As in `abstract new () => Date`
return this.tsParseFunctionOrConstructorType(
"TSConstructorType",
/* abstract */ true,
);
}
return this.tsParseUnionTypeOrHigher();
}
Expand Down
1 change: 1 addition & 0 deletions packages/babel-parser/src/types.js
Expand Up @@ -1250,6 +1250,7 @@ export type TsConstructorType = TsTypeBase &
TsSignatureDeclarationBase & {
type: "TSConstructorType",
typeAnnotation: TsTypeAnnotation,
abstract: boolean,
};

export type TsTypeReference = TsTypeBase & {
Expand Down
@@ -0,0 +1 @@
let x: abstract new () => void = X;
@@ -0,0 +1,52 @@
{
"type": "File",
"start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}},
"program": {
"type": "Program",
"start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}},
"declarations": [
{
"type": "VariableDeclarator",
"start":4,"end":34,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":34}},
"id": {
"type": "Identifier",
"start":4,"end":30,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":30},"identifierName":"x"},
"name": "x",
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":5,"end":30,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":30}},
"typeAnnotation": {
"type": "TSConstructorType",
"start":7,"end":30,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":30}},
"abstract": true,
"parameters": [],
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":23,"end":30,"loc":{"start":{"line":1,"column":23},"end":{"line":1,"column":30}},
"typeAnnotation": {
"type": "TSVoidKeyword",
"start":26,"end":30,"loc":{"start":{"line":1,"column":26},"end":{"line":1,"column":30}}
}
}
}
}
},
"init": {
"type": "Identifier",
"start":33,"end":34,"loc":{"start":{"line":1,"column":33},"end":{"line":1,"column":34},"identifierName":"X"},
"name": "X"
}
}
],
"kind": "let"
}
],
"directives": []
}
}
@@ -0,0 +1 @@
let x: new () => void = X;
@@ -0,0 +1,52 @@
{
"type": "File",
"start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}},
"program": {
"type": "Program",
"start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}},
"declarations": [
{
"type": "VariableDeclarator",
"start":4,"end":25,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":25}},
"id": {
"type": "Identifier",
"start":4,"end":21,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":21},"identifierName":"x"},
"name": "x",
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":5,"end":21,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":21}},
"typeAnnotation": {
"type": "TSConstructorType",
"start":7,"end":21,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":21}},
"abstract": false,
"parameters": [],
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":14,"end":21,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":21}},
"typeAnnotation": {
"type": "TSVoidKeyword",
"start":17,"end":21,"loc":{"start":{"line":1,"column":17},"end":{"line":1,"column":21}}
}
}
}
}
},
"init": {
"type": "Identifier",
"start":24,"end":25,"loc":{"start":{"line":1,"column":24},"end":{"line":1,"column":25},"identifierName":"X"},
"name": "X"
}
}
],
"kind": "let"
}
],
"directives": []
}
}
@@ -0,0 +1,2 @@
type abstract = "abstract";
let x: abstract;
@@ -0,0 +1,65 @@
{
"type": "File",
"start":0,"end":44,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":16}},
"program": {
"type": "Program",
"start":0,"end":44,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":16}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSTypeAliasDeclaration",
"start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":27}},
"id": {
"type": "Identifier",
"start":5,"end":13,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":13},"identifierName":"abstract"},
"name": "abstract"
},
"typeAnnotation": {
"type": "TSLiteralType",
"start":16,"end":26,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":26}},
"literal": {
"type": "StringLiteral",
"start":16,"end":26,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":26}},
"extra": {
"rawValue": "abstract",
"raw": "\"abstract\""
},
"value": "abstract"
}
}
},
{
"type": "VariableDeclaration",
"start":28,"end":44,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":16}},
"declarations": [
{
"type": "VariableDeclarator",
"start":32,"end":43,"loc":{"start":{"line":2,"column":4},"end":{"line":2,"column":15}},
"id": {
"type": "Identifier",
"start":32,"end":43,"loc":{"start":{"line":2,"column":4},"end":{"line":2,"column":15},"identifierName":"x"},
"name": "x",
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":33,"end":43,"loc":{"start":{"line":2,"column":5},"end":{"line":2,"column":15}},
"typeAnnotation": {
"type": "TSTypeReference",
"start":35,"end":43,"loc":{"start":{"line":2,"column":7},"end":{"line":2,"column":15}},
"typeName": {
"type": "Identifier",
"start":35,"end":43,"loc":{"start":{"line":2,"column":7},"end":{"line":2,"column":15},"identifierName":"abstract"},
"name": "abstract"
}
}
}
},
"init": null
}
],
"kind": "let"
}
],
"directives": []
}
}
1 change: 1 addition & 0 deletions packages/babel-types/src/ast-types/generated/index.ts
Expand Up @@ -1772,6 +1772,7 @@ export interface TSConstructorType extends BaseNode {
typeParameters?: TSTypeParameterDeclaration | null;
parameters: Array<Identifier | RestElement>;
typeAnnotation?: TSTypeAnnotation | null;
abstract?: boolean | null;
}

export interface TSTypeReference extends BaseNode {
Expand Down
16 changes: 12 additions & 4 deletions packages/babel-types/src/definitions/typescript.ts
Expand Up @@ -157,14 +157,22 @@ defineType("TSThisType", {
fields: {},
});

const fnOrCtr = {
const fnOrCtrBase = {
aliases: ["TSType"],
visitor: ["typeParameters", "parameters", "typeAnnotation"],
fields: signatureDeclarationCommon,
};

defineType("TSFunctionType", fnOrCtr);
defineType("TSConstructorType", fnOrCtr);
defineType("TSFunctionType", {
...fnOrCtrBase,
fields: signatureDeclarationCommon,
});
defineType("TSConstructorType", {
...fnOrCtrBase,
fields: {
...signatureDeclarationCommon,
abstract: validateOptional(bool),
},
});

defineType("TSTypeReference", {
aliases: ["TSType"],
Expand Down

0 comments on commit e4588be

Please sign in to comment.