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 babel-core typings #14622

Merged
merged 14 commits into from Jun 11, 2022
8 changes: 5 additions & 3 deletions packages/babel-core/src/config/caching.ts
Expand Up @@ -348,7 +348,7 @@ class CacheConfigurator<SideChannel = void> {
function makeSimpleConfigurator(
cache: CacheConfigurator<any>,
): SimpleCacheConfigurator {
function cacheFn(val) {
function cacheFn(val: any) {
if (typeof val === "boolean") {
if (val) cache.forever();
else cache.never();
Expand All @@ -359,8 +359,10 @@ function makeSimpleConfigurator(
}
cacheFn.forever = () => cache.forever();
cacheFn.never = () => cache.never();
cacheFn.using = cb => cache.using(() => assertSimpleType(cb()));
cacheFn.invalidate = cb => cache.invalidate(() => assertSimpleType(cb()));
cacheFn.using = (cb: { (): SimpleType }) =>
cache.using(() => assertSimpleType(cb()));
cacheFn.invalidate = (cb: { (): SimpleType }) =>
cache.invalidate(() => assertSimpleType(cb()));

return cacheFn as any;
}
Expand Down
68 changes: 49 additions & 19 deletions packages/babel-core/src/config/config-chain.ts
Expand Up @@ -383,7 +383,12 @@ const loadFileChainWalker = makeChainWalker<ValidatedFile>({
buildFileLogger(file.filepath, context, baseLogger),
});

function* loadFileChain(input, context, files, baseLogger) {
function* loadFileChain(
input: ValidatedFile,
context: ConfigContext,
files: Set<ConfigFile>,
baseLogger: ConfigPrinter,
) {
const chain = yield* loadFileChainWalker(input, context, files, baseLogger);
if (chain) {
chain.files.add(input.filepath);
Expand Down Expand Up @@ -443,34 +448,55 @@ function buildFileLogger(
});
}

function buildRootDescriptors({ dirname, options }, alias, descriptors) {
function buildRootDescriptors(
{ dirname, options }: Partial<ValidatedFile>,
alias: string,
descriptors: (
dirname: string,
options: ValidatedOptions,
alias: string,
) => OptionsAndDescriptors,
) {
return descriptors(dirname, options, alias);
}

function buildProgrammaticLogger(_, context, baseLogger: ConfigPrinter | void) {
function buildProgrammaticLogger(
_: unknown,
context: ConfigContext,
baseLogger: ConfigPrinter | void,
) {
if (!baseLogger) {
return () => {};
}
return baseLogger.configure(context.showConfig, ChainFormatter.Programmatic, {
// @ts-expect-error caller may be void
callerName: context.caller?.name,
});
}

function buildEnvDescriptors(
{ dirname, options },
alias,
descriptors,
envName,
{ dirname, options }: Partial<ValidatedFile>,
alias: string,
descriptors: (
dirname: string,
options: ValidatedOptions,
alias: string,
) => OptionsAndDescriptors,
envName: string,
) {
const opts = options.env && options.env[envName];
return opts ? descriptors(dirname, opts, `${alias}.env["${envName}"]`) : null;
}

function buildOverrideDescriptors(
{ dirname, options },
alias,
descriptors,
index,
{ dirname, options }: Partial<ValidatedFile>,
alias: string,
descriptors: (
dirname: string,
options: ValidatedOptions,
alias: string,
) => OptionsAndDescriptors,
index: number,
) {
const opts = options.overrides && options.overrides[index];
if (!opts) throw new Error("Assertion failure - missing override");
Expand All @@ -479,11 +505,15 @@ function buildOverrideDescriptors(
}

function buildOverrideEnvDescriptors(
{ dirname, options },
alias,
descriptors,
index,
envName,
{ dirname, options }: Partial<ValidatedFile>,
alias: string,
descriptors: (
dirname: string,
options: ValidatedOptions,
alias: string,
) => OptionsAndDescriptors,
index: number,
envName: string,
) {
const override = options.overrides && options.overrides[index];
if (!override) throw new Error("Assertion failure - missing override");
Expand Down Expand Up @@ -850,9 +880,9 @@ function matchesPatterns(
}

function matchPattern(
pattern,
dirname,
pathToTest,
pattern: IgnoreItem,
dirname: string,
pathToTest: unknown,
context: ConfigContext,
): boolean {
if (typeof pattern === "function") {
Expand Down
4 changes: 2 additions & 2 deletions packages/babel-core/src/config/config-descriptors.ts
Expand Up @@ -126,8 +126,8 @@ export function createUncachedDescriptors(
// The returned result here is cached to represent a config object in
// memory, so we build and memoize the descriptors to ensure the same
// values are returned consistently.
let plugins;
let presets;
let plugins: UnloadedDescriptor[];
let presets: UnloadedDescriptor[];

return {
options: optionsWithResolvedBrowserslistConfigFile(options, dirname),
Expand Down
6 changes: 5 additions & 1 deletion packages/babel-core/src/config/files/configuration.ts
Expand Up @@ -150,7 +150,11 @@ export function* loadConfig(
* Read the given config file, returning the result. Returns null if no config was found, but will
* throw if there are parsing errors while loading a config.
*/
function readConfig(filepath, envName, caller): Handler<ConfigFile | null> {
function readConfig(
filepath: string,
envName: string,
caller: void | CallerMetadata,
): Handler<ConfigFile | null> {
const ext = path.extname(filepath);
return ext === ".js" || ext === ".cjs" || ext === ".mjs"
? readConfigJS(filepath, { envName, caller })
Expand Down
3 changes: 2 additions & 1 deletion packages/babel-core/src/config/files/import-meta-resolve.ts
Expand Up @@ -34,7 +34,8 @@ const importMetaResolveP: Promise<ImportMeta["resolve"]> =
// it throws because it's a module, will fallback to import().
process.execArgv.includes("--experimental-import-meta-resolve")
? import_("data:text/javascript,export default import.meta.resolve").then(
m => m.default || polyfill,
(m: { default: ImportMeta["resolve"] | undefined }) =>
m.default || polyfill,
() => polyfill,
)
: Promise.resolve(polyfill);
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-core/src/config/files/index-browser.ts
Expand Up @@ -72,7 +72,7 @@ export function* resolveShowConfigPath(
return null;
}

export const ROOT_CONFIG_FILENAMES = [];
export const ROOT_CONFIG_FILENAMES: string[] = [];

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function resolvePlugin(name: string, dirname: string): string | null {
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-core/src/config/files/module-types.ts
Expand Up @@ -6,7 +6,7 @@ import { createRequire } from "module";

const require = createRequire(import.meta.url);

let import_;
let import_: ((specifier: string | URL) => any) | undefined;
try {
// Node < 13.3 doesn't support import() syntax.
import_ = require("./import").default;
Expand Down
4 changes: 3 additions & 1 deletion packages/babel-core/src/config/files/types.ts
@@ -1,7 +1,9 @@
import type { InputOptions } from "..";

export type ConfigFile = {
filepath: string;
dirname: string;
options: {};
options: InputOptions;
};

export type IgnoreFile = {
Expand Down
15 changes: 9 additions & 6 deletions packages/babel-core/src/config/full.ts
Expand Up @@ -181,7 +181,7 @@ export default gensync<(inputOpts: unknown) => ResolvedConfig | null>(
pluginDescriptorsByPass[0].unshift(...initialPluginsDescriptors);

for (const descs of pluginDescriptorsByPass) {
const pass = [];
const pass: Plugin[] = [];
passes.push(pass);

for (let i = 0; i < descs.length; i++) {
Expand Down Expand Up @@ -223,8 +223,8 @@ export default gensync<(inputOpts: unknown) => ResolvedConfig | null>(
},
);

function enhanceError<T extends Function>(context, fn: T): T {
return function* (arg1, arg2) {
function enhanceError<T extends Function>(context: ConfigContext, fn: T): T {
return function* (arg1: unknown, arg2: unknown) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use Parameters<T>[0] and Parameters<T>[1]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem to be, it can't be passed into the Function.

Copy link
Contributor

@armano2 armano2 Jun 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should be able to use Parameters in here if you define proper correct type of T

i'm not sure what should be in here, but as simple example you can do something like this:

function enhanceError<T extends (arg1?: unknown, arg2?: unknown) => Generator<unknown>>(
  context: ConfigContext,
  fn: T,
): T {
  return function* (arg1: Parameters<T>[0], arg2: Parameters<T>[1]) {

see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html

try {
return yield* fn(arg1, arg2);
} catch (e) {
Expand Down Expand Up @@ -376,7 +376,7 @@ const instantiatePlugin = makeWeakCache(function* (
}

if (plugin.inherits) {
const inheritsDescriptor = {
const inheritsDescriptor: UnloadedDescriptor = {
name: undefined,
alias: `${alias}$inherits`,
value: plugin.inherits,
Expand Down Expand Up @@ -490,11 +490,14 @@ const instantiatePreset = makeWeakCacheSync(
},
);

function chain(a, b) {
function chain<Args extends any[]>(
a: undefined | ((...args: Args) => void),
b: undefined | ((...args: Args) => void),
) {
const fns = [a, b].filter(Boolean);
if (fns.length <= 1) return fns[0];

return function (this: unknown, ...args) {
return function (this: unknown, ...args: unknown[]) {
for (const fn of fns) {
fn.apply(this, args);
}
Expand Down
13 changes: 7 additions & 6 deletions packages/babel-core/src/config/helpers/config-api.ts
Expand Up @@ -47,23 +47,23 @@ export type PluginAPI = {
export function makeConfigAPI<SideChannel extends Context.SimpleConfig>(
cache: CacheConfigurator<SideChannel>,
): ConfigAPI {
const env: any = value =>
const env: EnvFunction = value =>
cache.using(data => {
if (typeof value === "undefined") return data.envName;
if (typeof value === "function") {
return assertSimpleType(value(data.envName));
}
if (!Array.isArray(value)) value = [value];

return value.some((entry: unknown) => {
return (Array.isArray(value) ? value : [value]).some(entry => {
if (typeof entry !== "string") {
throw new Error("Unexpected non-string value");
}
return entry === data.envName;
});
});

const caller = cb => cache.using(data => assertSimpleType(cb(data.caller)));
const caller = (cb: {
(CallerMetadata: void | CallerMetadata): SimpleType;
}) => cache.using(data => assertSimpleType(cb(data.caller)));

return {
version: coreVersion,
Expand Down Expand Up @@ -98,7 +98,8 @@ export function makePluginAPI<SideChannel extends Context.SimplePlugin>(
cache: CacheConfigurator<SideChannel>,
externalDependencies: Array<string>,
): PluginAPI {
const assumption = name => cache.using(data => data.assumptions[name]);
const assumption = (name: string) =>
cache.using(data => data.assumptions[name]);

return { ...makePresetAPI(cache, externalDependencies), assumption };
}
Expand Down
16 changes: 9 additions & 7 deletions packages/babel-core/src/config/index.ts
@@ -1,4 +1,5 @@
import gensync from "gensync";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Todo (for myself): Continue reviewing from this file.

import type { Gensync } from "gensync";

export type {
ResolvedConfig,
Expand Down Expand Up @@ -43,13 +44,14 @@ const createConfigItemRunner =
createConfigItemImpl,
);

const maybeErrback = runner => (opts: unknown, callback?: Function) => {
if (callback === undefined && typeof opts === "function") {
callback = opts;
opts = undefined;
}
return callback ? runner.errback(opts, callback) : runner.sync(opts);
};
const maybeErrback =
(runner: Gensync<any>) => (opts: unknown, callback?: any) => {
liuxingbaoyu marked this conversation as resolved.
Show resolved Hide resolved
if (callback === undefined && typeof opts === "function") {
callback = opts;
opts = undefined;
}
return callback ? runner.errback(opts, callback) : runner.sync(opts);
};

export const loadPartialConfig = maybeErrback(loadPartialConfigRunner);
export const loadPartialConfigSync = loadPartialConfigRunner.sync;
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-core/src/config/pattern-to-regex.ts
Expand Up @@ -11,7 +11,7 @@ const starPatLast = `(?:${substitution}${endSep})`;
const starStarPat = `${starPat}*?`;
const starStarPatLast = `${starPat}*?${starPatLast}?`;

function escapeRegExp(string) {
function escapeRegExp(string: string) {
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
}

Expand Down
6 changes: 3 additions & 3 deletions packages/babel-core/src/config/plugin.ts
Expand Up @@ -5,9 +5,9 @@ import type { PluginObject } from "./validation/plugins";
export default class Plugin {
key: string | undefined | null;
manipulateOptions?: (options: unknown, parserOpts: unknown) => void;
post?: Function;
pre?: Function;
visitor: {};
post?: PluginObject["post"];
pre?: PluginObject["pre"];
visitor: PluginObject["visitor"];

parserOverride?: Function;
generatorOverride?: Function;
Expand Down
6 changes: 4 additions & 2 deletions packages/babel-core/src/config/util.ts
Expand Up @@ -13,16 +13,18 @@ export function mergeOptions(
const targetObj = target[k] || (target[k] = {});
mergeDefaultFields(targetObj, parserOpts);
} else {
//@ts-expect-error
const val = source[k];
//@ts-expect-error
if (val !== undefined) target[k] = val as any;
}
}
}

function mergeDefaultFields<T extends {}>(target: T, source: T) {
function mergeDefaultFields(target: any, source: any) {
liuxingbaoyu marked this conversation as resolved.
Show resolved Hide resolved
for (const k of Object.keys(source)) {
const val = source[k];
if (val !== undefined) target[k] = val as any;
if (val !== undefined) target[k] = val;
}
}

Expand Down
Expand Up @@ -33,7 +33,7 @@ export type ValidatorSet = {

export type Validator<T> = (loc: OptionPath, value: unknown) => T;

export function msg(loc: NestingPath | GeneralPath) {
export function msg(loc: NestingPath | GeneralPath): string {
switch (loc.type) {
case "root":
return ``;
Expand Down Expand Up @@ -446,7 +446,7 @@ function assertBrowserVersion(loc: GeneralPath, value: unknown) {

export function assertAssumptions(
loc: GeneralPath,
value: unknown,
value: { [key: string]: unknown },
): { [name: string]: boolean } | void {
if (value === undefined) return;

Expand Down
2 changes: 1 addition & 1 deletion packages/babel-core/src/config/validation/options.ts
Expand Up @@ -296,7 +296,7 @@ export function validate(type: OptionsSource, opts: {}): ValidatedOptions {
);
}

function validateNested(loc: NestingPath, opts: {}) {
function validateNested(loc: NestingPath, opts: { [key: string]: unknown }) {
const type = getSource(loc);

assertNoDuplicateSourcemap(opts);
Expand Down
4 changes: 3 additions & 1 deletion packages/babel-core/src/config/validation/plugins.ts
Expand Up @@ -92,7 +92,9 @@ export type PluginObject<S extends PluginPass = PluginPass> = {
generatorOverride?: Function;
};

export function validatePluginObject(obj: {}): PluginObject {
export function validatePluginObject(obj: {
[key: string]: unknown;
}): PluginObject {
const rootPath: RootPath = {
type: "root",
source: "plugin",
Expand Down