Provide plugin/preset typings from plugin-utils#14499
Provide plugin/preset typings from plugin-utils#14499nicolo-ribaudo merged 22 commits intobabel:mainfrom
Conversation
| visitor: { | ||
| "OptionalCallExpression|OptionalMemberExpression"(path) { | ||
| "OptionalCallExpression|OptionalMemberExpression"( | ||
| path: NodePath<t.OptionalCallExpression | t.OptionalMemberExpression>, |
There was a problem hiding this comment.
We still have to manually annotate the input of the multiple-type selection visitors.
| rejectId?: t.Identifier; | ||
| } | ||
|
|
||
| export default declare<State>((api, options: Options) => { |
There was a problem hiding this comment.
A plugin can declare its own State definition, the state will be available as the second callback param of NodePath visitors.
However I have to export the State interface otherwise TS will complain at preset-env/src/available-plugins:
TS4082: Default export of the module has or is using private name 'State'.74 export default {
~~~~~~~~~~~~~~~~
75 "bugfix/transform-async-arrows-in-class": () => bugfixAsyncArrowsInClass,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
149 "transform-unicode-regex": () => transformUnicodeRegex,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
150 };
~~
I don't think the State should be exported, suggestions are welcome.
There was a problem hiding this comment.
Does TS also complain if we define it inline? i.e.
export default declare<{
requireId?: t.Identifier;
resolveId?: t.Identifier;
rejectId?: t.Identifier;
}>((api, options: Options) => {and if we use type instead of interface?
There was a problem hiding this comment.
Using type works as intended, thanks!
afb6f64 to
53453de
Compare
| } | ||
|
|
||
| function getBuiltIn(name, path, programPath) { | ||
| function getBuiltIn(name, programPath) { |
There was a problem hiding this comment.
The path is not used.
|
|
||
| manipulateOptions(opts, parserOpts) { | ||
| parserOpts.plugins.push(["importAssertions"]); | ||
| parserOpts.plugins.push("importAssertions"); |
There was a problem hiding this comment.
They are equivalent, but the type-checker favors the latter form, which is also more common.
|
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/51784/ |
| } | ||
|
|
||
| const { node } = func; | ||
| if (t.isMethod(node)) { |
There was a problem hiding this comment.
A method must not have id so this step can be advanced, which also helps narrowing down the types.
53453de to
c20d40b
Compare
| ) => SimpleType; | ||
| type TargetsFunction = () => Targets; | ||
| type AssumptionFunction = (name: string) => boolean | void; | ||
| type AssumptionFunction = (name: AssumptionName) => boolean; |
There was a problem hiding this comment.
Technically a plugin could be used with an old @babel/core version that doesn't know about a new assumption and thus returns undefined.
We could annotate this as (name: AssumptionName) => boolean | void: it's fine (and more helpful) if the parameter is more restrictive, but the return type should cover all the possibilities to avoid possible bugs caused by assuming that it's always a boolean.
There was a problem hiding this comment.
If we stick to the principle that an assumption always introduce certain non-spec constraints, I would not oppose to make it always return false for unknown assumptions. Otherwise plugins has to cast .assumption(name) to boolean by themselves.
There was a problem hiding this comment.
Well, there is at least noNewArrow that does api.assumption("noNewArrow") ?? true, so "just return false" doesn't work.
There was a problem hiding this comment.
Don't we want to default it to false in Babel 8? 🙂
| export default declare((api, opt: Options) => { | ||
| api.assertVersion(7); | ||
| const { types: t, template } = api; |
There was a problem hiding this comment.
Q: Does TS complain about destructuring?
There was a problem hiding this comment.
Nope. TS correctly picks up typeof import ("@babel/types") for t.
There was a problem hiding this comment.
I didn't select enough lines when commenting! The original code was export default declare(({ assertVersion, types: t, template }`, and I wondered if the destructuring directly in the param made it complain.
There was a problem hiding this comment.
destructuring directly in the param made it complain
Nope. I moved destructuring in param to body in order to avoid a wall of whitespace changes. In packages/babel-plugin-proposal-class-static-block/src/index.ts destructuring in param works as expected.
| rejectId?: t.Identifier; | ||
| } | ||
|
|
||
| export default declare<State>((api, options: Options) => { |
There was a problem hiding this comment.
Does TS also complain if we define it inline? i.e.
export default declare<{
requireId?: t.Identifier;
resolveId?: t.Identifier;
rejectId?: t.Identifier;
}>((api, options: Options) => {and if we use type instead of interface?
Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
…/index.ts Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
|
|
||
| const noDocumentAll = api.assumption("noDocumentAll"); | ||
| const pureGetters = api.assumption("pureGetters"); | ||
| const noDocumentAll = (api.assumption("noDocumentAll") ?? false) as boolean; |
There was a problem hiding this comment.
This is microsoft/TypeScript#40359. TS currently can not narrow down (boolean | void) ?? boolean to boolean
|
|
||
| if (has(options, "useBuiltIns")) { | ||
| if (options.useBuiltIns) { | ||
| if (options["useBuiltIns"]) { |
There was a problem hiding this comment.
I didn't add useBuiltIns and polyfill to Options because they have been removed prior to Babel 7.
In this PR we provides typings from
declare/declarePresetin@babel/helper-plugin-utils, which is used in every official Babel plugins.For most plugins with type-only visitors, type inference works without manual annotations.
We introduce a
declarePresetmethod for presets usage. I didn't figure out how to merge typing hints withdeclareso I end up with a new method.