Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add assertions signature for TypeScript #10543

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 10 additions & 4 deletions packages/babel-generator/src/generators/typescript.js
Expand Up @@ -197,11 +197,17 @@ export function TSTypeReference(node) {
}

export function TSTypePredicate(node) {
if (node.assertsModifier) {
this.word("asserts");
this.space();
}
this.print(node.parameterName);
this.space();
this.word("is");
this.space();
this.print(node.typeAnnotation.typeAnnotation);
if (node.typeAnnotation) {
this.space();
this.word("is");
this.space();
this.print(node.typeAnnotation.typeAnnotation);
}
}

export function TSTypeQuery(node) {
Expand Down
@@ -0,0 +1,2 @@
(x: any): asserts x => true;
(x: any): asserts x is boolean => true;
@@ -0,0 +1,3 @@
(x: any): asserts x => true;

(x: any): asserts x is boolean => true;
@@ -0,0 +1,2 @@
function f(x: any): asserts x {}
(function(x: any): asserts x is boolean {})
@@ -0,0 +1,3 @@
function f(x: any): asserts x {}

(function (x: any): asserts x is boolean {});
40 changes: 35 additions & 5 deletions packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -904,21 +904,34 @@ export default (superClass: Class<Parser>): Class<Parser> =>
const t: N.TsTypeAnnotation = this.startNode();
this.expect(returnToken);

const assertsModifier = this.tsTryParse(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this could be parser without using tryParse: it would be possible to parse the assert identifier and then convert it to a type annotation if the next token is not another identifier.

On the other hand, we use tryParse everywhere when parsing TypeScript. I think that it's better to be consistent here, and then the whole TS parser can be optimized on other PRs.

this.tsParseTypePredicateAssertsModifier.bind(this),
);

const typePredicateVariable =
this.tsIsIdentifier() &&
this.tsTryParse(this.tsParseTypePredicatePrefix.bind(this));

if (!typePredicateVariable) {
return this.tsParseTypeAnnotation(/* eatColon */ false, t);
if (!assertsModifier) {
// : type
return this.tsParseTypeAnnotation(/* eatColon */ false, t);
}

// : asserts foo
const node = this.startNodeAtNode(t);
node.parameterName = this.parseIdentifier();
node.assertsModifier = assertsModifier;
tanhauhau marked this conversation as resolved.
Show resolved Hide resolved
t.typeAnnotation = this.finishNode(node, "TSTypePredicate");
return this.finishNode(t, "TSTypeAnnotation");
}

// : foo is type
const type = this.tsParseTypeAnnotation(/* eatColon */ false);

const node: N.TsTypePredicate = this.startNodeAtNode(
typePredicateVariable,
);
const node = this.startNodeAtNode(t);
node.parameterName = typePredicateVariable;
node.typeAnnotation = type;
node.assertsModifier = assertsModifier;
t.typeAnnotation = this.finishNode(node, "TSTypePredicate");
return this.finishNode(t, "TSTypeAnnotation");
});
Expand Down Expand Up @@ -946,6 +959,23 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}

tsParseTypePredicateAssertsModifier(): boolean {
if (!this.tsIsIdentifier()) {
return false;
}

const id = this.parseIdentifier();
if (
id.name !== "asserts" ||
this.hasPrecedingLineBreak() ||
!this.tsIsIdentifier()
) {
return false;
}

return true;
}

tsParseTypeAnnotation(
eatColon = true,
t: N.TsTypeAnnotation = this.startNode(),
Expand Down
Expand Up @@ -73,12 +73,12 @@
},
"typeAnnotation": {
"type": "TSTypePredicate",
"start": 10,
"start": 8,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

"end": 21,
"loc": {
"start": {
"line": 1,
"column": 10
"column": 8
},
"end": {
"line": 1,
Expand Down
@@ -0,0 +1,3 @@
const assert1 = (value: unknown): asserts value is string => {}
const assert2 = (value: unknown): asserts value => {}
const assert3 = (value: unknown): asserts => {}