可用于函数声明的函数回调的Typescript类型

时间:2019-04-12 22:58:33

标签: typescript types

是否可以在Typescript中键入一个回调函数,以对类型系统中的以下两个不变量进行编码:

  1. 如果err == null,则x的类型为T
  2. 如果err!= null,则不能引用x(never?)
type Callback<T> = {
  (error: null, value: T): void;
  (error: Error): void;
};

// The function that takes the typed callback.
function incrementAsync(x: number, cb: Callback<number>): void {
  if (x === 0) {
    return cb(new Error());
  }

  cb(null, x + 1); // should type-check
  cb(new Error()); // should type-check

  cb(new Error(), 1) // should fail type-check
  cb(null);          // should fail type-check
}

这是我真正想要的功能签名:

// Error: This overload signature is not compatible 
//        with its implementation signature.
function definedCb1(e: Error);
function definedCb1(e: null, x: number): void {}
incrementAsync(10, definedCb1); // error with strictNullChecks

这是一个比较松散的函数签名,可以进行类型检查

// BAD because types are too loose but this passes type-check.
function definedCb2(e: Error|null, x?: number): void {
  if (e === null) {
    // Is there a way to type this function, so the ! is not necessary?
    console.log(x! + 1);
    return;
  }
  // error because x might be undefined.
  console.log(x + 2);
}
incrementAsync(20, definedCb2) // Works

Typescript Playground Link启用strictNullChecksnoImplicitAny

1 个答案:

答案 0 :(得分:1)

如果您打开strictNullChecks,则这符合您的要求。

interface Callback<T> {
  (error: Error): void;
  (error: null, value: T): void;
}

function incrementAsync(x: number, cb: Callback<number>): void {
  cb(new Error());          // works
  cb(null, x + 1);          // works

  cb(null);                 // error
  cb(new Error(), 'foo');   // error
  cb(null, 'foo');          // error
  cb(new Error(), 10);      // error    
}

这里是in the playground.

strictNullChecks标志可阻止being nullable types中的所有类型。