我对TypeScript重载不满意,事情会变得非常复杂。我正在寻找一种方法来从两个单独的函数组成“重载”。是否可以通过以下一个函数合并这两个函数,而该函数具有接受传递的相同参数的能力?所有类型都按顺序排列。
function fromFileQuery (a: FileQuery): FileQuery {
if (!a.path) throw new Error('missing path');
return {
path: a.path,
encoding: a.encoding || null,
flag: a.flag || FileSystemFlags.R
};
}
function fromFilePathOptions (...args: FilePathOptions): FileQuery {
const [path, fileQuery] = args;
return fromFileQuery({...fileQuery, path});
}
const getFileQuery = make([fromFileQuery, fromFilePathOptions])
getFileQuery
支持FileQuery
或FilePathOptions
的地方。
这是我走的远了:
type ArgumentTypes<F extends Function> = F extends (...args: infer A) => any ? A : never;
function make(fns: any[]): Function {
type input = ArgumentTypes<typeof fns[0]>;
type output = ReturnType<typeof fns[0]>;
return (...arg: input): output => {
}
}
const x = make([fromFileQuery, fromFilePathOptions]);
答案 0 :(得分:1)
在这种情况下获取锻炼的类型并不是特别困难。
我们首先需要捕获所有函数类型。最好使用tuples in rest parameters完成此操作。然后,我们需要获取函数的所有参数类型和所有返回类型。从3.1开始,我们可以使用mapped tuples。
type AllParameters<T> = { [P in keyof T]: T[P] extends (...a: any[])=> any ? Parameters<T[P]> : never }
type AllReturnTypes<T> = { [P in keyof T]: T[P] extends (...a: any[])=> any ? ReturnType<T[P]> : never }
function make<T extends Array<(...a: any[])=> any>>(...fns: T){
return (...arg: AllParameters<T>[number]): AllReturnTypes<T>[number] => {
for(var fn of fns){
if(fn.length === arg.length) {
return fn(...arg);
}
}
throw new Error("Not supported")
}
}
function fromFileQuery (a: FileQuery): FileQuery {
if (!a.path) throw new Error('missing path');
return {
path: a.path,
encoding: a.encoding || null,
flag: a.flag || FileSystemFlags.R
};
}
function fromFilePathOptions (path: string, fileQuery: FileQuery): FileQuery {
return fromFileQuery({...fileQuery, path});
}
const getFileQuery = make(fromFileQuery, fromFilePathOptions)
const x = make(fromFileQuery, fromFilePathOptions);
x({
flag: "",
encoding: "",
path: ""
});
x("", {
flag: "",
encoding: ""
})
更困难的部分是确定要调用的函数。在上面的示例中,我选择使用fn.length === arg.length
,因此选择要调用的函数。显然,这并不是在所有情况下的最佳解决方案。我们可能还会考虑添加一个额外的函数来决定要调用哪个函数。
希望这会有所帮助,让我知道我是否还能提供其他帮助,感谢您的反馈:)