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) {
|
if (!types.length) {
|
||||||
return t.createUnionTypeAnnotation(types);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (t.isTSTypeAnnotation(types[0]) && t.createTSUnionType) {
|
||||||
|
return t.createTSUnionType(types);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.createUnionTypeAnnotation(types);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConstantViolationsBefore(binding, path, functions) {
|
function getConstantViolationsBefore(binding, path, functions) {
|
||||||
@ -201,6 +207,13 @@ function getConditionalAnnotation(binding, path, name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (types.length) {
|
if (types.length) {
|
||||||
|
if (t.isTSTypeAnnotation(types[0]) && t.createTSUnionType) {
|
||||||
|
return {
|
||||||
|
typeAnnotation: t.createTSUnionType(types),
|
||||||
|
ifStatement,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
typeAnnotation: t.createUnionTypeAnnotation(types),
|
typeAnnotation: t.createUnionTypeAnnotation(types),
|
||||||
ifStatement,
|
ifStatement,
|
||||||
|
|||||||
@ -83,17 +83,29 @@ export function BinaryExpression(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function LogicalExpression() {
|
export function LogicalExpression() {
|
||||||
return t.createUnionTypeAnnotation([
|
const argumentTypes = [
|
||||||
this.get("left").getTypeAnnotation(),
|
this.get("left").getTypeAnnotation(),
|
||||||
this.get("right").getTypeAnnotation(),
|
this.get("right").getTypeAnnotation(),
|
||||||
]);
|
];
|
||||||
|
|
||||||
|
if (t.isTSTypeAnnotation(argumentTypes[0]) && t.createTSUnionType) {
|
||||||
|
return t.createTSUnionType(argumentTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.createUnionTypeAnnotation(argumentTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ConditionalExpression() {
|
export function ConditionalExpression() {
|
||||||
return t.createUnionTypeAnnotation([
|
const argumentTypes = [
|
||||||
this.get("consequent").getTypeAnnotation(),
|
this.get("consequent").getTypeAnnotation(),
|
||||||
this.get("alternate").getTypeAnnotation(),
|
this.get("alternate").getTypeAnnotation(),
|
||||||
]);
|
];
|
||||||
|
|
||||||
|
if (t.isTSTypeAnnotation(argumentTypes[0]) && t.createTSUnionType) {
|
||||||
|
return t.createTSUnionType(argumentTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.createUnionTypeAnnotation(argumentTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SequenceExpression() {
|
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 {
|
export function assertTSType(node: Object, opts?: Object = {}): void {
|
||||||
assert("TSType", node, opts);
|
assert("TSType", node, opts);
|
||||||
}
|
}
|
||||||
|
export function assertTSBaseType(node: Object, opts?: Object = {}): void {
|
||||||
|
assert("TSBaseType", node, opts);
|
||||||
|
}
|
||||||
export function assertNumberLiteral(node: Object, opts: Object): void {
|
export function assertNumberLiteral(node: Object, opts: Object): void {
|
||||||
console.trace(
|
console.trace(
|
||||||
"The node type NumberLiteral has been renamed to NumericLiteral",
|
"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 PRIVATE_TYPES = FLIPPED_ALIAS_KEYS["Private"];
|
||||||
export const TSTYPEELEMENT_TYPES = FLIPPED_ALIAS_KEYS["TSTypeElement"];
|
export const TSTYPEELEMENT_TYPES = FLIPPED_ALIAS_KEYS["TSTypeElement"];
|
||||||
export const TSTYPE_TYPES = FLIPPED_ALIAS_KEYS["TSType"];
|
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) {
|
for (const type of tsKeywordTypes) {
|
||||||
defineType(type, {
|
defineType(type, {
|
||||||
aliases: ["TSType"],
|
aliases: ["TSType", "TSBaseType"],
|
||||||
visitor: [],
|
visitor: [],
|
||||||
fields: {},
|
fields: {},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
defineType("TSThisType", {
|
defineType("TSThisType", {
|
||||||
aliases: ["TSType"],
|
aliases: ["TSType", "TSBaseType"],
|
||||||
visitor: [],
|
visitor: [],
|
||||||
fields: {},
|
fields: {},
|
||||||
});
|
});
|
||||||
@ -300,7 +300,7 @@ defineType("TSMappedType", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
defineType("TSLiteralType", {
|
defineType("TSLiteralType", {
|
||||||
aliases: ["TSType"],
|
aliases: ["TSType", "TSBaseType"],
|
||||||
visitor: ["literal"],
|
visitor: ["literal"],
|
||||||
fields: {
|
fields: {
|
||||||
literal: validateType([
|
literal: validateType([
|
||||||
|
|||||||
@ -10,6 +10,7 @@ export * from "./asserts/generated";
|
|||||||
// builders
|
// builders
|
||||||
export { default as createTypeAnnotationBasedOnTypeof } from "./builders/flow/createTypeAnnotationBasedOnTypeof";
|
export { default as createTypeAnnotationBasedOnTypeof } from "./builders/flow/createTypeAnnotationBasedOnTypeof";
|
||||||
export { default as createUnionTypeAnnotation } from "./builders/flow/createUnionTypeAnnotation";
|
export { default as createUnionTypeAnnotation } from "./builders/flow/createUnionTypeAnnotation";
|
||||||
|
export { default as createTSUnionType } from "./builders/typescript/createTSUnionType";
|
||||||
export * from "./builders/generated";
|
export * from "./builders/generated";
|
||||||
|
|
||||||
// clone
|
// 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;
|
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 {
|
export function isNumberLiteral(node: ?Object, opts?: Object): boolean {
|
||||||
console.trace(
|
console.trace(
|
||||||
"The node type NumberLiteral has been renamed to NumericLiteral",
|
"The node type NumberLiteral has been renamed to NumericLiteral",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user