打字稿:函数的并集

时间:2018-07-01 09:29:39

标签: typescript

有两种函数类型,一种返回string,另一种返回Promise<string>。现在,我想要一个包装它们的函数,但是在调用fn

时,我必须区分每个包裹
type FuncTypes = (...args: any[]) => string | Promise<string>

function callFunc(fn: FuncTypes, ...args: any[]) {
  // distinguish fn returns string or Promise<string>
  // if fn returns string
    return new Promise<string>(r => r(fn.call(this, ...args)))
  // if fn returns a Promise
    return fn.call(this, ...args)
}

另一种情况是过载:

type FuncA = (...args: any[]) => string
type FuncB = (...args: any[]) => Promise<string>

function callFunc(fn: FuncA, ...args: any[]): Promise<string>
function callFunc(fn: FuncB, ...args: any[]): Promise<string>
function callFunc(fn: any, ...args: any[]): Promise<string> {
  // if fn is instanceof FuncA
  // do sth.
  // else if fn is instanceof FuncB
  // do sth
}

尽管我们可以简单地使用const returned = fn(..args); typeof returned === 'string'来检查返回的类型,但这不是一般的解决方案。如果函数类型为() => AnInterface|AnotherInterface,则很难使用typeofinstanceof来检查返回类型。

有什么通用的方法可以区分它们吗?还是应该为每种类型编写两个函数?

1 个答案:

答案 0 :(得分:1)

在这种情况下

  

有两种函数类型,一种返回字符串,另一种返回Promise。现在,我想要一个包装它们的函数,但是在调用fn时我必须区分每个包裹

在这种特定情况下, jsonobjects = $.grep(jsonobjects, function( value ) { return value.id !== id; }); 可能就是这样:

callFunc

如果function callFunc(fn: FuncTypes, ...args: any[]) { return <Promise<string>>Promise.resolve(fn.call(this, ...args)); } 返回承诺,则fn的承诺将被Promise.resolve返回的承诺所替代;否则,您将获得一个已解决的承诺,将返回值fn作为其解决值。

一般情况下

  

有什么通用的方法可以区分它们吗?

不是在运行时,除非您以某种方式(稍后再进行注释)对其进行注释。 TypeScript的类型信息仅在编译时。

  

还是我应该为每种类型编写两个函数?

那可能是最好的。

您可以对函数进行注释,例如,通过在函数上放置一个属性来指示其返回类型:

fn

到那时,您正在复制类型信息(一次用于TypeScript,再次一次用于您自己的代码)。

因此,编写两个函数的解决方案可能是最好的。