transform-spread: create TS types (not Flow) when using TS (#11378)
* ➕ add test fixture * ➕ add removeTypeDuplicates for typescript * ➕ add createTSUnionType for typescript * 💊 fix ConditionalExpression for typescript * 💊 fix ConditionalExpression * 💊 fix added test case * ➕ add new line at the end of the file * 💊 types.every(f) => f(types[0]) * 🔄 bug => foo * ➕ add TSBaseType * ➕ add conditions NOT to break backward compatibility
This commit is contained in:
parent
c85aafdff6
commit
6b8f6ab2de
@ -91,9 +91,15 @@ function getTypeAnnotationBindingConstantViolations(binding, path, name) {
|
||||
}
|
||||
}
|
||||
|
||||
if (types.length) {
|
||||
return t.createUnionTypeAnnotation(types);
|
||||
if (!types.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.isTSTypeAnnotation(types[0]) && t.createTSUnionType) {
|
||||
return t.createTSUnionType(types);
|
||||
}
|
||||
|
||||
return t.createUnionTypeAnnotation(types);
|
||||
}
|
||||
|
||||
function getConstantViolationsBefore(binding, path, functions) {
|
||||
@ -201,6 +207,13 @@ function getConditionalAnnotation(binding, path, name) {
|
||||
}
|
||||
|
||||
if (types.length) {
|
||||
if (t.isTSTypeAnnotation(types[0]) && t.createTSUnionType) {
|
||||
return {
|
||||
typeAnnotation: t.createTSUnionType(types),
|
||||
ifStatement,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
typeAnnotation: t.createUnionTypeAnnotation(types),
|
||||
ifStatement,
|
||||
|
||||
@ -83,17 +83,29 @@ export function BinaryExpression(node) {
|
||||
}
|
||||
|
||||
export function LogicalExpression() {
|
||||
return t.createUnionTypeAnnotation([
|
||||
const argumentTypes = [
|
||||
this.get("left").getTypeAnnotation(),
|
||||
this.get("right").getTypeAnnotation(),
|
||||
]);
|
||||
];
|
||||
|
||||
if (t.isTSTypeAnnotation(argumentTypes[0]) && t.createTSUnionType) {
|
||||
return t.createTSUnionType(argumentTypes);
|
||||
}
|
||||
|
||||
return t.createUnionTypeAnnotation(argumentTypes);
|
||||
}
|
||||
|
||||
export function ConditionalExpression() {
|
||||
return t.createUnionTypeAnnotation([
|
||||
const argumentTypes = [
|
||||
this.get("consequent").getTypeAnnotation(),
|
||||
this.get("alternate").getTypeAnnotation(),
|
||||
]);
|
||||
];
|
||||
|
||||
if (t.isTSTypeAnnotation(argumentTypes[0]) && t.createTSUnionType) {
|
||||
return t.createTSUnionType(argumentTypes);
|
||||
}
|
||||
|
||||
return t.createUnionTypeAnnotation(argumentTypes);
|
||||
}
|
||||
|
||||
export function SequenceExpression() {
|
||||
|
||||
13
packages/babel-traverse/test/fixtures/type-reference/input.ts
vendored
Normal file
13
packages/babel-traverse/test/fixtures/type-reference/input.ts
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
function foo() {
|
||||
const x = 1 ? a() : b();
|
||||
|
||||
return [...x];
|
||||
}
|
||||
|
||||
function a(): number[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
function b(): number[] {
|
||||
return [];
|
||||
}
|
||||
4
packages/babel-traverse/test/fixtures/type-reference/options.json
vendored
Normal file
4
packages/babel-traverse/test/fixtures/type-reference/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"plugins": ["transform-spread"],
|
||||
"presets": ["typescript"]
|
||||
}
|
||||
@ -1202,6 +1202,9 @@ export function assertTSTypeElement(node: Object, opts?: Object = {}): void {
|
||||
export function assertTSType(node: Object, opts?: Object = {}): void {
|
||||
assert("TSType", node, opts);
|
||||
}
|
||||
export function assertTSBaseType(node: Object, opts?: Object = {}): void {
|
||||
assert("TSBaseType", node, opts);
|
||||
}
|
||||
export function assertNumberLiteral(node: Object, opts: Object): void {
|
||||
console.trace(
|
||||
"The node type NumberLiteral has been renamed to NumericLiteral",
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
import { TSUnionType } from "../generated";
|
||||
import removeTypeDuplicates from "../../modifications/typescript/removeTypeDuplicates";
|
||||
|
||||
/**
|
||||
* Takes an array of `types` and flattens them, removing duplicates and
|
||||
* returns a `UnionTypeAnnotation` node containg them.
|
||||
*/
|
||||
export default function createTSUnionType(
|
||||
typeAnnotations: Array<Object>,
|
||||
): Object {
|
||||
const types = typeAnnotations.map(type => type.typeAnnotations);
|
||||
const flattened = removeTypeDuplicates(types);
|
||||
|
||||
if (flattened.length === 1) {
|
||||
return flattened[0];
|
||||
} else {
|
||||
return TSUnionType(flattened);
|
||||
}
|
||||
}
|
||||
@ -51,3 +51,4 @@ export const JSX_TYPES = FLIPPED_ALIAS_KEYS["JSX"];
|
||||
export const PRIVATE_TYPES = FLIPPED_ALIAS_KEYS["Private"];
|
||||
export const TSTYPEELEMENT_TYPES = FLIPPED_ALIAS_KEYS["TSTypeElement"];
|
||||
export const TSTYPE_TYPES = FLIPPED_ALIAS_KEYS["TSType"];
|
||||
export const TSBASETYPE_TYPES = FLIPPED_ALIAS_KEYS["TSBaseType"];
|
||||
|
||||
@ -143,14 +143,14 @@ const tsKeywordTypes = [
|
||||
|
||||
for (const type of tsKeywordTypes) {
|
||||
defineType(type, {
|
||||
aliases: ["TSType"],
|
||||
aliases: ["TSType", "TSBaseType"],
|
||||
visitor: [],
|
||||
fields: {},
|
||||
});
|
||||
}
|
||||
|
||||
defineType("TSThisType", {
|
||||
aliases: ["TSType"],
|
||||
aliases: ["TSType", "TSBaseType"],
|
||||
visitor: [],
|
||||
fields: {},
|
||||
});
|
||||
@ -300,7 +300,7 @@ defineType("TSMappedType", {
|
||||
});
|
||||
|
||||
defineType("TSLiteralType", {
|
||||
aliases: ["TSType"],
|
||||
aliases: ["TSType", "TSBaseType"],
|
||||
visitor: ["literal"],
|
||||
fields: {
|
||||
literal: validateType([
|
||||
|
||||
@ -10,6 +10,7 @@ export * from "./asserts/generated";
|
||||
// builders
|
||||
export { default as createTypeAnnotationBasedOnTypeof } from "./builders/flow/createTypeAnnotationBasedOnTypeof";
|
||||
export { default as createUnionTypeAnnotation } from "./builders/flow/createUnionTypeAnnotation";
|
||||
export { default as createTSUnionType } from "./builders/typescript/createTSUnionType";
|
||||
export * from "./builders/generated";
|
||||
|
||||
// clone
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
import {
|
||||
isTSAnyKeyword,
|
||||
isTSUnionType,
|
||||
isTSBaseType,
|
||||
} from "../../validators/generated";
|
||||
|
||||
/**
|
||||
* Dedupe type annotations.
|
||||
*/
|
||||
export default function removeTypeDuplicates(
|
||||
nodes: Array<Object>,
|
||||
): Array<Object> {
|
||||
const generics = {};
|
||||
const bases = {};
|
||||
|
||||
// store union type groups to circular references
|
||||
const typeGroups = [];
|
||||
|
||||
const types = [];
|
||||
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i];
|
||||
if (!node) continue;
|
||||
|
||||
// detect duplicates
|
||||
if (types.indexOf(node) >= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// this type matches anything
|
||||
if (isTSAnyKeyword(node.type)) {
|
||||
return [node];
|
||||
}
|
||||
|
||||
// Analogue of FlowBaseAnnotation
|
||||
if (isTSBaseType(node)) {
|
||||
bases[node.type] = node;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isTSUnionType(node)) {
|
||||
if (typeGroups.indexOf(node.types) < 0) {
|
||||
nodes = nodes.concat(node.types);
|
||||
typeGroups.push(node.types);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: add generic types
|
||||
|
||||
types.push(node);
|
||||
}
|
||||
|
||||
// add back in bases
|
||||
for (const type of Object.keys(bases)) {
|
||||
types.push(bases[type]);
|
||||
}
|
||||
|
||||
// add back in generics
|
||||
for (const name of Object.keys(generics)) {
|
||||
types.push(generics[name]);
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
@ -4611,6 +4611,36 @@ export function isTSType(node: ?Object, opts?: Object): boolean {
|
||||
|
||||
return false;
|
||||
}
|
||||
export function isTSBaseType(node: ?Object, opts?: Object): boolean {
|
||||
if (!node) return false;
|
||||
|
||||
const nodeType = node.type;
|
||||
if (
|
||||
nodeType === "TSBaseType" ||
|
||||
"TSAnyKeyword" === nodeType ||
|
||||
"TSBooleanKeyword" === nodeType ||
|
||||
"TSBigIntKeyword" === nodeType ||
|
||||
"TSNeverKeyword" === nodeType ||
|
||||
"TSNullKeyword" === nodeType ||
|
||||
"TSNumberKeyword" === nodeType ||
|
||||
"TSObjectKeyword" === nodeType ||
|
||||
"TSStringKeyword" === nodeType ||
|
||||
"TSSymbolKeyword" === nodeType ||
|
||||
"TSUndefinedKeyword" === nodeType ||
|
||||
"TSUnknownKeyword" === nodeType ||
|
||||
"TSVoidKeyword" === nodeType ||
|
||||
"TSThisType" === nodeType ||
|
||||
"TSLiteralType" === nodeType
|
||||
) {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
} else {
|
||||
return shallowEqual(node, opts);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
export function isNumberLiteral(node: ?Object, opts?: Object): boolean {
|
||||
console.trace(
|
||||
"The node type NumberLiteral has been renamed to NumericLiteral",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user