Skip to content

Commit ead9c85

Browse files
Andyaminmarashi
Andy
authored andcommitted
TypeScript: Support conditional types syntax (babel#7404)
microsoft/TypeScript#21316 and microsoft/TypeScript#21496
1 parent f2d543e commit ead9c85

File tree

16 files changed

+587
-1
lines changed

16 files changed

+587
-1
lines changed

packages/babel-generator/src/generators/typescript.js

+22
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,28 @@ export function tsPrintUnionOrIntersectionType(node, sep) {
256256
});
257257
}
258258

259+
export function TSConditionalType(node) {
260+
this.print(node.checkType);
261+
this.space();
262+
this.word("extends");
263+
this.space();
264+
this.print(node.extendsType);
265+
this.space();
266+
this.token("?");
267+
this.space();
268+
this.print(node.trueType);
269+
this.space();
270+
this.token(":");
271+
this.space();
272+
this.print(node.falseType);
273+
}
274+
275+
export function TSInferType(node) {
276+
this.token("infer");
277+
this.space();
278+
this.print(node.typeParameter);
279+
}
280+
259281
export function TSParenthesizedType(node) {
260282
this.token("(");
261283
this.print(node.typeAnnotation, node);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
type Element<T> = T extends (infer U)[] ? U : T;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
type Element<T> = T extends (infer U)[] ? U : T;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let x: number extends string ? boolean : null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let x: number extends string ? boolean : null;

packages/babel-types/README.md

+29
Original file line numberDiff line numberDiff line change
@@ -1875,6 +1875,22 @@ Aliases: `TSTypeElement`
18751875

18761876
---
18771877

1878+
### tSConditionalType
1879+
```javascript
1880+
t.tsConditionalType(checkType, extendsType, trueType, falseType)
1881+
```
1882+
1883+
See also `t.isTSConditionalType(node, opts)` and `t.assertTSConditionalType(node, opts)`.
1884+
1885+
Aliases: `TSType`
1886+
1887+
- `checkType`: `TSType` (required)
1888+
- `extendsType`: `TSType` (required)
1889+
- `trueType`: `TSType` (required)
1890+
- `falseType`: `TSType` (required)
1891+
1892+
---
1893+
18781894
### tSConstructSignatureDeclaration
18791895
```javascript
18801896
t.tsConstructSignatureDeclaration(typeParameters, parameters, typeAnnotation)
@@ -2074,6 +2090,19 @@ Aliases: `TSType`
20742090

20752091
---
20762092

2093+
### tSInferType
2094+
```javascript
2095+
t.tsInferType(typeParameter)
2096+
```
2097+
2098+
See also `t.isTSInferType(node, opts)` and `t.assertTSInferType(node, opts)`.
2099+
2100+
Aliases: `TSType`
2101+
2102+
- `typeParameter`: `TSType` (required)
2103+
2104+
---
2105+
20772106
### tSInterfaceBody
20782107
```javascript
20792108
t.tsInterfaceBody(body)

packages/babel-types/src/asserts/generated/index.js

+9
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,15 @@ export function assertTSIntersectionType(
801801
): void {
802802
assert("TSIntersectionType", node, opts);
803803
}
804+
export function assertTSConditionalType(
805+
node: Object,
806+
opts?: Object = {},
807+
): void {
808+
assert("TSConditionalType", node, opts);
809+
}
810+
export function assertTSInferType(node: Object, opts?: Object = {}): void {
811+
assert("TSInferType", node, opts);
812+
}
804813
export function assertTSParenthesizedType(
805814
node: Object,
806815
opts?: Object = {},

packages/babel-types/src/builders/generated/index.js

+10
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,16 @@ export function TSIntersectionType(...args: Array<any>): Object {
774774
}
775775
export { TSIntersectionType as tsIntersectionType };
776776
export { TSIntersectionType as tSIntersectionType };
777+
export function TSConditionalType(...args: Array<any>): Object {
778+
return builder("TSConditionalType", ...args);
779+
}
780+
export { TSConditionalType as tsConditionalType };
781+
export { TSConditionalType as tSConditionalType };
782+
export function TSInferType(...args: Array<any>): Object {
783+
return builder("TSInferType", ...args);
784+
}
785+
export { TSInferType as tsInferType };
786+
export { TSInferType as tSInferType };
777787
export function TSParenthesizedType(...args: Array<any>): Object {
778788
return builder("TSParenthesizedType", ...args);
779789
}

packages/babel-types/src/definitions/typescript.js

+19
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,25 @@ const unionOrIntersection = {
223223
defineType("TSUnionType", unionOrIntersection);
224224
defineType("TSIntersectionType", unionOrIntersection);
225225

226+
defineType("TSConditionalType", {
227+
aliases: ["TSType"],
228+
visitor: ["checkType", "extendsType", "trueType", "falseType"],
229+
fields: {
230+
checkType: validateType("TSType"),
231+
extendsType: validateType("TSType"),
232+
trueType: validateType("TSType"),
233+
falseType: validateType("TSType"),
234+
},
235+
});
236+
237+
defineType("TSInferType", {
238+
aliases: ["TSType"],
239+
visitor: ["typeParameter"],
240+
fields: {
241+
typeParameter: validateType("TSType"),
242+
},
243+
});
244+
226245
defineType("TSParenthesizedType", {
227246
aliases: ["TSType"],
228247
visitor: ["typeAnnotation"],

packages/babel-types/src/validators/generated/index.js

+6
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,12 @@ export function isTSUnionType(node: Object, opts?: Object): boolean {
608608
export function isTSIntersectionType(node: Object, opts?: Object): boolean {
609609
return is("TSIntersectionType", node, opts);
610610
}
611+
export function isTSConditionalType(node: Object, opts?: Object): boolean {
612+
return is("TSConditionalType", node, opts);
613+
}
614+
export function isTSInferType(node: Object, opts?: Object): boolean {
615+
return is("TSInferType", node, opts);
616+
}
611617
export function isTSParenthesizedType(node: Object, opts?: Object): boolean {
612618
return is("TSParenthesizedType", node, opts);
613619
}

packages/babylon/src/plugins/typescript.js

+27-1
Original file line numberDiff line numberDiff line change
@@ -617,11 +617,22 @@ export default (superClass: Class<Parser>): Class<Parser> =>
617617
return this.finishNode(node, "TSTypeOperator");
618618
}
619619

620+
tsParseInferType(): N.TsInferType {
621+
const node = this.startNode();
622+
this.expectContextual("infer");
623+
const typeParameter = this.startNode();
624+
typeParameter.name = this.parseIdentifierName(typeParameter.start);
625+
node.typeParameter = this.finishNode(typeParameter, "TypeParameter");
626+
return this.finishNode(node, "TSInferType");
627+
}
628+
620629
tsParseTypeOperatorOrHigher(): N.TsType {
621630
const operator = ["keyof", "unique"].find(kw => this.isContextual(kw));
622631
return operator
623632
? this.tsParseTypeOperator(operator)
624-
: this.tsParseArrayTypeOrHigher();
633+
: this.isContextual("infer")
634+
? this.tsParseInferType()
635+
: this.tsParseArrayTypeOrHigher();
625636
}
626637

627638
tsParseUnionOrIntersectionType(
@@ -774,6 +785,21 @@ export default (superClass: Class<Parser>): Class<Parser> =>
774785
tsParseType(): N.TsType {
775786
// Need to set `state.inType` so that we don't parse JSX in a type context.
776787
assert(this.state.inType);
788+
const type = this.tsParseNonConditionalType();
789+
if (this.hasPrecedingLineBreak() || !this.eat(tt._extends)) {
790+
return type;
791+
}
792+
const node: N.TsConditionalType = this.startNodeAtNode(type);
793+
node.checkType = type;
794+
node.extendsType = this.tsParseNonConditionalType();
795+
this.expect(tt.question);
796+
node.trueType = this.tsParseType();
797+
this.expect(tt.colon);
798+
node.falseType = this.tsParseType();
799+
return this.finishNode(node, "TSConditionalType");
800+
}
801+
802+
tsParseNonConditionalType(): N.TsType {
777803
if (this.tsIsStartOfFunctionType()) {
778804
return this.tsParseFunctionOrConstructorType("TSFunctionType");
779805
}

packages/babylon/src/types.js

+13
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,19 @@ export type TsIntersectionType = TsUnionOrIntersectionTypeBase & {
11541154
type: "TSIntersectionType",
11551155
};
11561156

1157+
export type TsConditionalType = TsTypeBase & {
1158+
type: "TSConditionalType",
1159+
checkType: TsType,
1160+
extendsType: TsType,
1161+
trueType: TsType,
1162+
falseType: tsType,
1163+
};
1164+
1165+
export type InferType = TsTypeBase & {
1166+
type: "TSInferType",
1167+
typeParameter: TypeParameter,
1168+
};
1169+
11571170
export type TsParenthesizedType = TsTypeBase & {
11581171
type: "TSParenthesizedType",
11591172
typeAnnotation: TsType,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
type Element<T> = T extends (infer U)[] ? U : T;

0 commit comments

Comments
 (0)