diff --git a/packages/babel-parser/src/parser/base.ts b/packages/babel-parser/src/parser/base.ts index 5158a34f2a0a..ea2a937bb52e 100644 --- a/packages/babel-parser/src/parser/base.ts +++ b/packages/babel-parser/src/parser/base.ts @@ -5,7 +5,11 @@ import type ScopeHandler from "../util/scope"; import type ExpressionScopeHandler from "../util/expression-scope"; import type ClassScopeHandler from "../util/class-scope"; import type ProductionParameterHandler from "../util/production-parameter"; -import type { PluginConfig } from "../typings"; +import type { + ParserPluginWithOptions, + PluginConfig, + PluginOptions, +} from "../typings"; export default class BaseParser { // Properties set by constructor in index.js @@ -54,7 +58,12 @@ export default class BaseParser { } } - getPluginOption(plugin: string, name: string) { - return this.plugins.get(plugin)?.[name]; + getPluginOption< + PluginName extends ParserPluginWithOptions[0], + OptionName extends keyof PluginOptions, + >(plugin: PluginName, name: OptionName) { + return (this.plugins.get(plugin) as null | PluginOptions)?.[ + name + ]; } } diff --git a/packages/babel-parser/src/plugin-utils.ts b/packages/babel-parser/src/plugin-utils.ts index 4421b24bba55..0ac4728168ee 100644 --- a/packages/babel-parser/src/plugin-utils.ts +++ b/packages/babel-parser/src/plugin-utils.ts @@ -1,5 +1,9 @@ import type Parser from "./parser"; -import type { PluginConfig } from "./typings"; +import type { + ParserPluginWithOptions, + PluginConfig, + PluginOptions, +} from "./typings"; export type Plugin = PluginConfig; @@ -47,11 +51,10 @@ export function hasPlugin( }); } -export function getPluginOption( - plugins: PluginList, - name: string, - option: string, -) { +export function getPluginOption< + PluginName extends ParserPluginWithOptions[0], + OptionName extends keyof PluginOptions, +>(plugins: PluginList, name: PluginName, option: OptionName) { const plugin = plugins.find(plugin => { if (Array.isArray(plugin)) { return plugin[0] === name; @@ -60,9 +63,8 @@ export function getPluginOption( } }); - if (plugin && Array.isArray(plugin)) { - // @ts-expect-error Fixme: should check whether option is defined - return plugin[1][option]; + if (plugin && Array.isArray(plugin) && plugin.length > 1) { + return (plugin[1] as PluginOptions)[option]; } return null; diff --git a/packages/babel-parser/src/typings.ts b/packages/babel-parser/src/typings.ts index 95a649b54cb0..d932bba05572 100644 --- a/packages/babel-parser/src/typings.ts +++ b/packages/babel-parser/src/typings.ts @@ -7,13 +7,11 @@ export type Plugin = | "classProperties" | "classStaticBlock" // Enabled by default | "decimal" - | "decorators" | "decorators-legacy" | "decoratorAutoAccessors" | "destructuringPrivate" | "doExpressions" | "dynamicImport" - | "estree" | "exportDefaultFrom" | "exportNamespaceFrom" // deprecated | "flow" @@ -24,8 +22,6 @@ export type Plugin = | "jsx" | "logicalAssignment" | "importAssertions" - // @deprecated - | "moduleAttributes" | "moduleBlocks" | "moduleStringNames" | "nullishCoalescingOperator" @@ -34,25 +30,29 @@ export type Plugin = | "optionalCatchBinding" | "optionalChaining" | "partialApplication" - | "pipelineOperator" | "placeholders" | "privateIn" // Enabled by default - | "recordAndTuple" | "regexpUnicodeSets" | "throwExpressions" | "topLevelAwait" - | "typescript" - | "v8intrinsic"; - -export type PluginConfig = Plugin | ParserPluginWithOptions; + | "v8intrinsic" + | ParserPluginWithOptions[0]; export type ParserPluginWithOptions = | ["decorators", DecoratorsPluginOptions] + | ["estree", { classFeatures?: boolean }] + // @deprecated + | ["moduleAttributes", { version: "may-2020" }] | ["pipelineOperator", PipelineOperatorPluginOptions] | ["recordAndTuple", RecordAndTuplePluginOptions] | ["flow", FlowPluginOptions] | ["typescript", TypeScriptPluginOptions]; +export type PluginConfig = Plugin | ParserPluginWithOptions; + +export type PluginOptions = + Extract[1]; + export interface DecoratorsPluginOptions { decoratorsBeforeExport?: boolean; }