Skip to content

Commit

Permalink
feat(babel‑types): Add type definitions for Node assertion methods
Browse files Browse the repository at this point in the history
  • Loading branch information
ExE-Boss committed Jul 28, 2020
1 parent 3a0aa8e commit d942ed7
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 15 deletions.
5 changes: 5 additions & 0 deletions packages/babel-types/package.json
Expand Up @@ -15,6 +15,11 @@
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
"typesVersions": {
">=3.7": {
"lib/*.d.ts": ["lib/*.ts37.d.ts"]
}
},
"dependencies": {
"@babel/helper-validator-identifier": "^7.10.4",
"lodash": "^4.17.19",
Expand Down
29 changes: 24 additions & 5 deletions packages/babel-types/scripts/generators/flow.js
Expand Up @@ -112,16 +112,35 @@ for (const type in t.NODE_FIELDS) {
}
}

for (let i = 0; i < t.TYPES.length; i++) {
let decl = `declare function is${t.TYPES[i]}(node: ?Object, opts?: ?Object): boolean`;
lines.push(
// assert/
`declare function function assertNode(node: ?Object): void`,
);

const typeCheckLineGroups = [[], []];
for (const typeName of t.TYPES.sort()) {
let decl = `declare function is${typeName}(node: ?Object, opts?: ?Object): boolean`;
const isDeprecated = typeName in t.DEPRECATED_KEYS;
const realName = isDeprecated ? t.DEPRECATED_KEYS[typeName] : typeName;

if (t.NODE_FIELDS[t.TYPES[i]]) {
decl += ` %checks (node instanceof ${NODE_PREFIX}${t.TYPES[i]})`;
if (t.NODE_FIELDS[realName]) {
decl += ` %checks (node instanceof ${NODE_PREFIX}${realName})`;
}

lines.push(decl);
if (isDeprecated) {
typeCheckLineGroups[0].push(`/** @deprecated Use \`is${realName}\` */`);
typeCheckLineGroups[1].push(`/** @deprecated Use \`assert${realName}\` */`);
}

typeCheckLineGroups[0].push(decl);
typeCheckLineGroups[1].push(
`declare function assert${typeName}(node: ?Object, opts?: ?Object): void;`
);
}

lines.push(...typeCheckLineGroups[0]);
lines.push(...typeCheckLineGroups[1]);

lines.push(
// builders/
// eslint-disable-next-line max-len
Expand Down
64 changes: 54 additions & 10 deletions packages/babel-types/scripts/generators/typescript.js
@@ -1,9 +1,13 @@
"use strict";

const fs = require("fs");
const path = require("path");
const t = require("../../");
const stringifyValidator = require("../utils/stringifyValidator");
const toFunctionName = require("../utils/toFunctionName");

const outDir = path.join(__dirname, "../../lib");

let code = `// NOTE: This file is autogenerated. Do not modify.
// See packages/babel-types/scripts/generators/typescript.js for script used.
Expand Down Expand Up @@ -51,6 +55,18 @@ export type Node = ${t.TYPES.sort().join(" | ")};\n\n`;

//

let ts37code = `\
// NOTE: This file is autogenerated. Do not modify.
// See packages/babel-types/scripts/generators/typescript.js for script used.
export * from "./index";
`;

const ts37lines = [
// assert/
`export function assertNode(node: object | null | undefined): asserts node is import("./index").Node;`,
];
const lines = [];

for (const type in t.NODE_FIELDS) {
Expand Down Expand Up @@ -119,27 +135,49 @@ for (const type in t.NODE_FIELDS) {
}
}

lines.push(
// assert/
`export function assertNode(node: object | null | undefined): void`,
);

const typeCheckLineGroups = [[], []];
for (const typeName of t.TYPES) {
const isDeprecated = typeName in t.DEPRECATED_KEYS;
const realName = isDeprecated ? t.DEPRECATED_KEYS[typeName] : typeName;

const result =
t.NODE_FIELDS[typeName] || t.FLIPPED_ALIAS_KEYS[typeName]
? `node is ${typeName}`
t.NODE_FIELDS[realName] || t.FLIPPED_ALIAS_KEYS[realName]
? `node is import("./index").${realName}`
: "boolean";

lines.push(
`export function is${typeName}(node: object | null | undefined, opts?: object | null): ${result};`,
if (isDeprecated) {
const deprecatedAssert = `/** @deprecated Use \`assert${realName}\` */`;
typeCheckLineGroups[0].push(`/** @deprecated Use \`is${realName}\` */`);
typeCheckLineGroups[1].push(deprecatedAssert);
ts37lines.push(deprecatedAssert);
}

typeCheckLineGroups[0].push(
`export function is${typeName}(node: object | null | undefined, opts?: object | null): ${result};`
);

typeCheckLineGroups[1].push(
`export function assert${typeName}(node: object | null | undefined, opts?: object | null): void;`
);

ts37lines.push(
// TypeScript 3.7: https://github.com/microsoft/TypeScript/pull/32695 will allow assert declarations
// eslint-disable-next-line max-len
`// export function assert${typeName}(node: object | null | undefined, opts?: object | null): asserts ${
result === "boolean" ? "node" : result
`export function assert${typeName}(node: object | null | undefined, opts?: object | null): ${
result === "boolean" ? "void" : `asserts ${result}`
};`
);
}

lines.push(
// assert/
// Commented out as this declaration requires TypeScript 3.7 (what do?)
`// export function assertNode(obj: any): asserts obj is Node`,
lines.push(...typeCheckLineGroups[0]);
lines.push(...typeCheckLineGroups[1]);

lines.push(
// builders/
// eslint-disable-next-line max-len
`export function createTypeAnnotationBasedOnTypeof(type: 'string' | 'number' | 'undefined' | 'boolean' | 'function' | 'object' | 'symbol'): StringTypeAnnotation | VoidTypeAnnotation | NumberTypeAnnotation | BooleanTypeAnnotation | GenericTypeAnnotation`,
Expand Down Expand Up @@ -333,10 +371,16 @@ code += "}\n\n";

code += lines.join("\n") + "\n";

ts37code += ts37lines.join("\n") + "\n";

//

process.stdout.write(code);

// This has to be written to a separate file, which means we can't easily
// use `process.stdout.write` without doing some stream splitting trickery:
fs.writeFileSync(path.join(outDir, "index.ts37.d.ts"), ts37code, { encoding: "utf8" });

//

function areAllRemainingFieldsNullable(fieldName, fieldNames, fields) {
Expand Down

0 comments on commit d942ed7

Please sign in to comment.