假设我具有以下功能签名:
function someFunction(arg1?: number, arg2?: string, arg3?: string|string[]) {}
每个参数都是可选的,因此应将其称为
someFunction(undefined, undefined, [''])
如果我想省略其中一些。
现在,使用Node-NormalizeArguments之类的库,我可以按以下方式包装此函数:
function wrappedFunction() {
const normalizedArgs = args(arguments, [
args.number(undefined),
args.string(undefined),
args.oneOf([
args.array,
args.string
], undefined)
]);
return someFunction(...normalizedArgs)
}
,因此允许将其称为
someFunction([''])
获得相同的结果。
当然已经存在一些缺陷(我通过使用args.array丢失了string[]
类型检查),但是这些缺陷可以在库代码中得到解决。真正的问题是:
如何定义此新包装函数的类型? (最好不要详细列出所有可能的参数组合,或者至少不要手工完成)
答案 0 :(得分:2)
您可以使用一堆类型别名来生成带有所有参数子集的一组重载签名:
// `CAaOb`: first `a` parameters are already assigned, remaining `b` are
// optional. `X` is the union of the types of the optional parameters following
// the last assigned parameter that are assumed to have already been skipped,
// meaning that the runtime type of the next argument must not belong to `X`.
type CA0O0<X, R> = () => R;
type CA1O0<A1, X, R> = (a1: A1) => R;
type CA0O1<X, O1, R> = CA1O0<Exclude<O1, X>, never, R> & CA0O0<X | O1, R>;
type CA2O0<A1, A2, X, R> = (a1: A1, a2: A2) => R;
type CA1O1<A1, X, O1, R> = CA2O0<A1, Exclude<O1, X>, never, R> & CA1O0<A1, X | O1, R>;
type CA0O2<X, O1, O2, R> = CA1O1<Exclude<O1, X>, never, O2, R> & CA0O1<X | O1, O2, R>;
type CA3O0<A1, A2, A3, X, R> = (a1: A1, a2: A2, a3: A3) => R;
type CA2O1<A1, A2, X, O1, R> = CA3O0<A1, A2, Exclude<O1, X>, never, R> & CA2O0<A1, A2, X | O1, R>;
type CA1O2<A1, X, O1, O2, R> = CA2O1<A1, Exclude<O1, X>, never, O2, R> & CA1O1<A1, X | O1, O2, R>;
type CA0O3<X, O1, O2, O3, R> = CA1O2<Exclude<O1, X>, never, O2, O3, R> & CA0O2<X | O1, O2, O3, R>;
function someFunction(arg1?: number, arg2?: string, arg3?: string|string[]) { }
const wrappedFunction: CA0O3<never, number, string, string | string[], void> = function() {
const normalizedArgs = args(arguments, [
args.number(undefined),
args.string(undefined),
args.oneOf([
args.array,
args.string
], undefined)
]);
return someFunction(...normalizedArgs);
};
当然,您会丢失参数名称。如果要保留它们,则必须编写脚本来生成过载签名。