Skip to content

Commit

Permalink
add assertions signature for TypeScript (#10543)
Browse files Browse the repository at this point in the history
* add asserts predicate

* fix flow

* babel-generator for typescript assertions

* babel-types for typescript assertions

* asserts modifier as boolean
  • Loading branch information
tanhauhau authored and nicolo-ribaudo committed Oct 29, 2019
1 parent 4cd93ab commit 38a3063
Show file tree
Hide file tree
Showing 19 changed files with 1,721 additions and 17 deletions.
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(
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;
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,
"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 => {}

0 comments on commit 38a3063

Please sign in to comment.