【发布时间】:2020-12-26 16:03:04
【问题描述】:
我正在构建一个包含大量命令和选项的大型 CLI 应用程序,其中一些在命令中重复使用。我正在使用yargs 库,我发现自己正在创建如下辅助函数:
const withFoo = (yargs: Argv) =>
yargs.option('foo', {
type: 'string',
});
const withBar = (yargs: Argv) =>
yargs.option('bar', {
type: 'string',
});
他们像这样使用它们:
const bazOptionsBuilder = (yargs: Argv) =>
withFoo(withBar(yargs)).option('baz', { type: 'string' });
现在,我想创建一个帮助函数来减少嵌套,我可以这样做:
const bazOptionsBuilder = withOptions(
withFoo,
withBar,
/* ... possibly more here */
(yargs) => yargs.option('baz', { type: 'string' }),
);
实现withOptions 函数相对简单,但我在输入它时遇到了困难。到目前为止,我想出了:
import { Argv } from 'yargs';
type YargsBuilder<A extends Argv> = (y: Argv) => A;
type ArgsOf<T> = T extends Argv<infer A> ? A : never;
export function withOptions<A extends Argv<any>, B extends Argv<any>>(
a: YargsBuilder<A>,
b: YargsBuilder<B>,
): YargsBuilder<Argv<ArgsOf<A> & ArgsOf<B>>>;
export function withOptions<A extends Argv<any>, B extends Argv<any>, C extends Argv<any>>(
a: YargsBuilder<A>,
b: YargsBuilder<B>,
c: YargsBuilder<C>,
): YargsBuilder<Argv<ArgsOf<A> & ArgsOf<B> & ArgsOf<C>>>;
// ... and more ...
但这迫使我为withOptions 的任意数量的参数编写类型。是否可以为 withOptions 创建一个单一类型签名,告诉 typescript 传入的任意数量的 YargsBuilders,返回类型将是所有这些类型的联合?
【问题讨论】:
-
我的理解是否正确:您希望
withOptions成为一个接受函数列表的函数 - 每个函数都以Argv作为输入,对其进行变异并返回它 - 并返回一个函数给定一个Argv依次通过每个转换器函数? -
如果是这种情况,你为什么需要特殊的打字?
-
为什么不使用配置对象方法而不是构建器?
-
@Aron,是的,就是这样。它需要特殊类型,因为我希望返回函数的结果返回类型是所有传入函数的返回值的联合类型
-
@Lesiak 构建器模式来自
yargs,而不是来自我的代码。我无法改变它。
标签: typescript typescript-generics