【发布时间】:2017-09-10 09:30:37
【问题描述】:
我在将泛型应用于 TypeScript 定义时遇到问题。
定义是:
export function readFile(path: PathLike | number, options: { encoding?: null; flag?: string; } | undefined | null, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void;
export function readFile(path: PathLike | number, options: { encoding: string; flag?: string; } | string, callback: (err: NodeJS.ErrnoException, data: string) => void): void;
export function readFile(path: PathLike | number, options: { encoding?: string | null; flag?: string; } | string | undefined | null, callback: (err: NodeJS.ErrnoException, data: string | Buffer) => void): void;
export function readFile(path: PathLike | number, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void;
如您所见,它们接受 2 到 3 个参数,最后一个始终是回调。
现在我的通用是:
function cbCall<Ret, Arg1, Arg2>(
fun: (arg1: Arg1, arg2: Arg2, cb: (error: any, result: Ret) => any) => any,
obj: any,
arg1: Arg1,
arg2: Arg2
): Context<Ret>;
由于它需要一个带有 3 个参数的函数(最后一个是回调),我猜它会匹配前 3 个定义中的一个。但是,当我尝试像这样使用cbCall 时:
CL.cbCall(
fs.readFile,
fs,
'filename',
{ encoding: 'utf-8' }
);
我得到错误:
Argument of type '{ encoding: string; }' is not assignable to parameter of type '(err: ErrnoException, data: Buffer) => void'.
所以它以某种方式期望 arg2 成为 cb 应该是的样子。
如果我删除 Arg2 模板参数并将其替换为 object,它可以工作,但这对于我的用例来说不够通用。
请解释为什么会发生这种情况以及我是否可以实现我想要实现的目标。
编辑:使用 cbCall<string, string, object>(...) 也可以,但又一次失败了。
编辑:我将示例简化为:
function fun(arg: string, cb: (err: string, res: string) => void);
function fun(cb: (err: string, res: string) => void): void;
function fun(arg: any, cb?: any): void {
// noop
}
function call<Ret, Arg>(fun: (arg: Arg, cb: (err: string, res: Ret) => void) => any, arg: Arg) {
// noop
}
// this works
call<string, string>(fun,'test');
// Argument of type '"test"' is not assignable to parameter of type '(err: string, res: string) => void'.
call(fun,'test'); //
更改前两行的顺序也可以修复它。 但是不应该使用第一个匹配的声明而不是最后一个吗?
【问题讨论】:
-
在此处删除链接以防我没有时间完成此答案:github.com/Microsoft/TypeScript/blob/master/doc/…
标签: typescript generics