打字稿错误优先回调打字(noImplicitAny,strictNullChecks)

时间:2017-03-05 02:32:47

标签: node.js typescript interface callback typing

我想使用带有noImplicitAnystrictNullChecks的typscript在项目中声明一个带有错误优先回调的函数。

有没有办法声明interfacetype允许两个不同的签名并在调用时有效?

最简单,最直接的方法是将其声明为

function example(callback: (err?: Error, result?: {data: any}) => void) {
    callback(undefined, {data: "hello"});
}

然而,这允许我在callback()内调用example(没有参数),这不是我们想要做的事情,因为应始终使用错误或结果调用回调。 / p>

function example(callback: (err: Error | undefined, result:  {data: any} | undefined) => void) {
    callback(undefined, {data: "hello"});
}

这不允许example()。必须使用2个参数调用回调。

然而,这两种模式都意味着errresult都可以undefined。这并不完美,因为以下内容会导致错误。

example((err, result) => {
    if(err) { console.error(err); return; }

    console.log(result.data);
});

由于result 可以undefined,我们不能假设它具有属性data。要解决此问题,我必须断言第二个参数是调用example((err, result: {data: any}) => void)时的内容,或者在result

中包含与if(result)的任何交互。

我想声明回调始终被称为 与< callback(undefined, { data: "Hello" }) callback(Error, undefined)。 这两个参数永远不会被定义。

我发现声明这是

的工作方式
interface ICallback<r> {
    (err: undefined, result: r): void;
    (err: Error, result: undefined): void;
};

function example(callback: ICallback<{data: any}>) {
    callback(undefined, {data: "hello"});
}

这似乎有效,在example内,调用callback(new Error(), {data: "error"})callback(undefined, undefined)会导致错误。

然而;当我然后使用这个example函数时;

example((err, result) => {
    ...
});

errresult都隐含any。有没有办法声明允许(undefined, ISomething)(ISomethingElse, undefined)签名的回调函数,这意味着如果参数1未定义,我们可以期望定义参数2?

2 个答案:

答案 0 :(得分:1)

  

然而,允许我调用example(()=&gt; void)这不是我想要的东西,因为我们应该处理至少错误。

情况总是如此。回调可以忽略任何参数。

这是因为TypeScript的功能兼容性:https://basarat.gitbooks.io/typescript/content/docs/types/type-compatibility.html#number-of-arguments

更多

在某种程度上,这类似于您可以自由地忽略捕获异常的方式。因此,如果需要,回调可以忽略处理错误。

答案 1 :(得分:0)

我最接近的是:

interface NodeCallback<T> {
  (err: any, result?: undefined | null): void;
  (err: undefined | null, result: T): void;
}

对于cb: NodeCallback<string>,这允许:

  • cb('boom')
  • cb(new Error('boom'))
  • cb('boom', null)
  • cb('boom', undefined)
  • cb(null, 'box')
  • cb(undefined, 'box')

但不是cb(new Error('boom'), 'box')cb(null, 123)

不幸的是,它只对消费者方面有好处(也就是调用回调的那个) - 在遇到过载签名时,打字稿将放弃上下文推断的参数类型(或者,等效地,签名):

// 'err' and 'result' have type 'any', which will error with --strict / --noImplicitAny
const cb: NodeCallback<number> = (err, result) => {};

幸运的是,有一个recently opened PR可以解决这个问题!