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

Improve preset/plugin-typescript typings #14603

Merged
merged 4 commits into from May 26, 2022
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
10 changes: 5 additions & 5 deletions packages/babel-plugin-transform-typescript/src/enum.ts
Expand Up @@ -39,7 +39,7 @@ export default function transpileEnum(
throw new Error(`Unexpected enum parent '${path.parent.type}`);
}

function seen(parentPath: NodePath<t.Node>) {
function seen(parentPath: NodePath<t.Node>): boolean {
if (parentPath.isExportDeclaration()) {
return seen(parentPath.parentPath);
}
Expand Down Expand Up @@ -193,12 +193,12 @@ export function translateEnumValues(

// Based on the TypeScript repository's `evalConstant` in `checker.ts`.
function evaluate(
expr,
expr: t.Node,
seen: PreviousEnumMembers,
): number | string | typeof undefined {
return evalConstant(expr);

function evalConstant(expr): number | typeof undefined {
function evalConstant(expr: t.Node): number | typeof undefined {
switch (expr.type) {
case "StringLiteral":
return expr.value;
Expand All @@ -225,7 +225,7 @@ function evaluate(
function evalUnaryExpression({
argument,
operator,
}): number | typeof undefined {
}: t.UnaryExpression): number | typeof undefined {
const value = evalConstant(argument);
if (value === undefined) {
return undefined;
Expand All @@ -243,7 +243,7 @@ function evaluate(
}
}

function evalBinaryExpression(expr): number | typeof undefined {
function evalBinaryExpression(expr: t.BinaryExpression): number | undefined {
const left = evalConstant(expr.left);
if (left === undefined) {
return undefined;
Expand Down
23 changes: 17 additions & 6 deletions packages/babel-plugin-transform-typescript/src/index.ts
Expand Up @@ -2,7 +2,7 @@ import { declare } from "@babel/helper-plugin-utils";
import syntaxTypeScript from "@babel/plugin-syntax-typescript";
import { types as t, template } from "@babel/core";
import { injectInitialization } from "@babel/helper-create-class-features-plugin";
import type { NodePath } from "@babel/traverse";
import type { Binding, NodePath } from "@babel/traverse";
import type { Options as SyntaxOptions } from "@babel/plugin-syntax-typescript";

import transpileConstEnum from "./const-enum";
Expand Down Expand Up @@ -149,15 +149,15 @@ export default declare((api, opts: Options) => {
if (node.declare) node.declare = null;
if (node.override) node.override = null;
},
method({ node }) {
method({ node }: NodePath<t.ClassMethod | t.ClassPrivateMethod>) {
if (node.accessibility) node.accessibility = null;
if (node.abstract) node.abstract = null;
if (node.optional) node.optional = null;
if (node.override) node.override = null;

// Rest handled by Function visitor
},
constructor(path, classPath) {
constructor(path: NodePath<t.ClassMethod>, classPath: NodePath<t.Class>) {
if (path.node.accessibility) path.node.accessibility = null;
// Collects parameter properties so that we can add an assignment
// for each of them in the constructor body
Expand Down Expand Up @@ -487,7 +487,11 @@ export default declare((api, opts: Options) => {
path.get("body.body").forEach(child => {
if (child.isClassMethod() || child.isClassPrivateMethod()) {
if (child.node.kind === "constructor") {
classMemberVisitors.constructor(child, path);
classMemberVisitors.constructor(
// @ts-expect-error A constructor must not be a private method
child,
path,
);
} else {
classMemberVisitors.method(child);
}
Expand All @@ -512,7 +516,7 @@ export default declare((api, opts: Options) => {
},

TSModuleDeclaration(path) {
transpileNamespace(path, t, allowNamespaces);
transpileNamespace(path, allowNamespaces);
},

TSInterfaceDeclaration(path) {
Expand Down Expand Up @@ -614,7 +618,9 @@ export default declare((api, opts: Options) => {
return node;
}

function visitPattern({ node }) {
function visitPattern({
node,
}: NodePath<t.Identifier | t.Pattern | t.RestElement>) {
if (node.typeAnnotation) node.typeAnnotation = null;
if (t.isIdentifier(node) && node.optional) node.optional = null;
// 'access' and 'readonly' are only for parameter properties, so constructor visitor will handle them.
Expand All @@ -625,6 +631,11 @@ export default declare((api, opts: Options) => {
programPath,
pragmaImportName,
pragmaFragImportName,
}: {
binding: Binding;
programPath: NodePath<t.Program>;
pragmaImportName: string;
pragmaFragImportName: string;
}) {
for (const path of binding.referencePaths) {
if (!isInType(path)) {
Expand Down
46 changes: 24 additions & 22 deletions packages/babel-plugin-transform-typescript/src/namespace.ts
@@ -1,29 +1,33 @@
import { template, types as t } from "@babel/core";
import type { NodePath } from "@babel/traverse";

export default function transpileNamespace(path, t, allowNamespaces) {
export default function transpileNamespace(
path: NodePath<t.TSModuleDeclaration>,
allowNamespaces: boolean,
) {
if (path.node.declare || path.node.id.type === "StringLiteral") {
path.remove();
return;
}

if (!allowNamespaces) {
throw path.hub.file.buildCodeFrameError(
path.node.id,
"Namespace not marked type-only declare." +
" Non-declarative namespaces are only supported experimentally in Babel." +
" To enable and review caveats see:" +
" https://babeljs.io/docs/en/babel-plugin-transform-typescript",
);
throw path
.get("id")
.buildCodeFrameError(
"Namespace not marked type-only declare." +
" Non-declarative namespaces are only supported experimentally in Babel." +
" To enable and review caveats see:" +
" https://babeljs.io/docs/en/babel-plugin-transform-typescript",
);
}

const name = path.node.id.name;
const value = handleNested(path, t, t.cloneDeep(path.node));
const value = handleNested(path, t.cloneNode(path.node, true));
const bound = path.scope.hasOwnBinding(name);
if (path.parent.type === "ExportNamedDeclaration") {
if (!bound) {
path.parentPath.insertAfter(value);
path.replaceWith(getDeclaration(t, name));
path.replaceWith(getDeclaration(name));
path.scope.registerDeclaration(path.parentPath);
} else {
path.parentPath.replaceWith(value);
Expand All @@ -32,18 +36,18 @@ export default function transpileNamespace(path, t, allowNamespaces) {
path.replaceWith(value);
} else {
path.scope.registerDeclaration(
path.replaceWithMultiple([getDeclaration(t, name), value])[0],
path.replaceWithMultiple([getDeclaration(name), value])[0],
);
}
}

function getDeclaration(t, name) {
function getDeclaration(name: string) {
return t.variableDeclaration("let", [
t.variableDeclarator(t.identifier(name)),
]);
}

function getMemberExpression(t, name, itemName) {
function getMemberExpression(name: string, itemName: string) {
return t.memberExpression(t.identifier(name), t.identifier(itemName));
}

Expand Down Expand Up @@ -79,7 +83,7 @@ function handleVariableDeclaration(
for (const declarator of declarations) {
declarator.init = t.assignmentExpression(
"=",
getMemberExpression(t, name, declarator.id.name),
getMemberExpression(name, declarator.id.name),
declarator.init,
);
}
Expand All @@ -95,7 +99,7 @@ function handleVariableDeclaration(
assignments.push(
t.assignmentExpression(
"=",
getMemberExpression(t, name, idName),
getMemberExpression(name, idName),
t.cloneNode(bindingIdentifiers[idName]),
),
);
Expand All @@ -113,9 +117,8 @@ function buildNestedAmbiendModuleError(path: NodePath, node: t.Node) {

function handleNested(
path: NodePath,
t: typeof import("@babel/types"),
node: t.TSModuleDeclaration,
parentExport?,
parentExport?: t.Expression,
) {
const names = new Set();
const realName = node.id;
Expand All @@ -142,7 +145,7 @@ function handleNested(
throw buildNestedAmbiendModuleError(path, subNode);
}

const transformed = handleNested(path, t, subNode);
const transformed = handleNested(path, subNode);
const moduleName = subNode.id.name;
if (names.has(moduleName)) {
namespaceTopLevel[i] = transformed;
Expand All @@ -151,7 +154,7 @@ function handleNested(
namespaceTopLevel.splice(
i++,
1,
getDeclaration(t, moduleName),
getDeclaration(moduleName),
transformed,
);
}
Expand Down Expand Up @@ -191,7 +194,7 @@ function handleNested(
t.expressionStatement(
t.assignmentExpression(
"=",
getMemberExpression(t, name, itemName),
getMemberExpression(name, itemName),
t.identifier(itemName),
),
),
Expand All @@ -215,7 +218,6 @@ function handleNested(

const transformed = handleNested(
path,
t,
subNode.declaration,
t.identifier(name),
);
Expand All @@ -227,7 +229,7 @@ function handleNested(
namespaceTopLevel.splice(
i++,
1,
getDeclaration(t, moduleName),
getDeclaration(moduleName),
transformed,
);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/babel-preset-typescript/src/index.ts
Expand Up @@ -18,7 +18,7 @@ export default declarePreset((api, opts: Options) => {
} = normalizeOptions(opts);

const pluginOptions = process.env.BABEL_8_BREAKING
? (isTSX, disallowAmbiguousJSXLike) => ({
? (isTSX: boolean, disallowAmbiguousJSXLike: boolean) => ({
allowNamespaces,
disallowAmbiguousJSXLike,
isTSX,
Expand All @@ -27,7 +27,7 @@ export default declarePreset((api, opts: Options) => {
onlyRemoveTypeImports,
optimizeConstEnums,
})
: (isTSX, disallowAmbiguousJSXLike) => ({
: (isTSX: boolean, disallowAmbiguousJSXLike: boolean) => ({
allowDeclareFields: opts.allowDeclareFields,
allowNamespaces,
disallowAmbiguousJSXLike,
Expand Down