Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Improve plugin item typings#17801

Open
JLHwung wants to merge 4 commits intobabel:mainfrom
JLHwung:improve-plugin-item-typings
Open

Improve plugin item typings#17801
JLHwung wants to merge 4 commits intobabel:mainfrom
JLHwung:improve-plugin-item-typings

Conversation

@JLHwung
Copy link
Contributor

@JLHwung JLHwung commented Feb 16, 2026

Q                       A
Fixed Issues? #17778 (comment)
Patch: Bug Fix?
Major: Breaking Change?
Minor: New Feature?
Tests Added + Pass? Yes
Documentation PR Link
Any Dependency Changes?
License MIT

/cc @sapphi-red.

@babel-bot
Copy link
Collaborator

babel-bot commented Feb 16, 2026

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/61056

| [PresetTarget, object]
| [PresetTarget, object, string];
| PresetTarget<Option>
| [PresetTarget<Option>, Partial<Option>]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This change would allow users to explicitly type check preset options: For example,

import babelPresetEnv from "@babel/preset-env";
import type { Options as BabelPresetEnvOptions } from "@babel/preset-env";
import type { PresetTarget } from "@babel/core";

export default {
  presets: [
    // TS will throw `foo` is not defined in BabelPresetEnvOptions
    [babelPresetEnv, { targets: "chrome 123", foo: "string" }] satisifies PresetTarget<BabelPresetEnvOptions>
  ]
} 

But I didn't figure out how to make it an implicit constraint.

Copy link
Member

Choose a reason for hiding this comment

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

Would something like

export default {
  presets: [
    // TS will throw `foo` is not defined in BabelPresetEnvOptions
    [babelPresetEnv, { targets: "chrome 123", foo: "string" }]
  ]
} as BabelConfig

work, or not because TS cannot infer from babelPresetEnv to the second element of the list?

Choose a reason for hiding this comment

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

AFAIK TS calculates the constraints for the generics only when it's a type parameter. So it would require a function call.

import * as babel from '@babel/core';

function p<Option>(p: babel.PresetTarget<Option>, o: Partial<Option>) {
  return [p, o];
}

babel.transformSync('', {
    p(babelPresetEnv, {
      bugfixes: true,
      modules: false,
      // input suggestion works here
    }),
  ],
});

I guess the input suggestion doesn't work with transformSync because type InputOptions has plugins?: PluginItem[], which is the same as plugins?: PluginItem<object>[].

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a very good point, we could consider exporting two type-aware utilities pluginWithOptions, presetWithOptions such that the plugin/preset option can be properly type checked.

@nicolo-ribaudo @liuxingbaoyu WDYT?

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 16, 2026

Open in StackBlitz

commit: e88896f

| [PresetTarget, object]
| [PresetTarget, object, string];
| PresetTarget<Option>
| [PresetTarget<Option>, Partial<Option>]
Copy link
Member

Choose a reason for hiding this comment

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

Why are the Options partial?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question, this is to workaround the current preset-env option definition:

export type Options = {
bugfixes: boolean;
configPath: string;
corejs: CorejsOption;
debug: boolean;
exclude: PluginListOption;
forceAllTransforms: boolean;
ignoreBrowserslistConfig: boolean;
include: PluginListOption;
modules: ModuleOption;
shippedProposals: boolean;
targets: {
esmodules?: boolean;
} & InputTargets;
useBuiltIns: BuiltInsOption;
browserslistEnv: string;
};

The options here should have marked every property as optional, but the non-optional one is also handy to type the normalized options.

Copy link
Member

Choose a reason for hiding this comment

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

Could we move Partial<...> to the preset-env export in the index file, rather than just re-exporting Options as-is?

It'd be great to be able to get type errors when required options are missing.

@sapphi-red
Copy link

I've tested the types on stackblitz and is working for me as well 👍
https://stackblitz.com/edit/bxshcqvs?file=index.ts

@JLHwung JLHwung force-pushed the improve-plugin-item-typings branch from 81e3d00 to e88896f Compare February 25, 2026 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants