首页 > 解决方案 > 打字稿:功能的联合

问题描述

有两种函数类型,一种返回string,另一种返回 a 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'来检查返回的类型,但这不是一个通用的解决方案。如果函数类型是,使用or() => AnInterface|AnotherInterface很难检查返回类型。typeofinstanceof

有什么通用的方法来区分它们吗?或者我应该为每种类型编写两个函数?

标签: typescript

解决方案


在那种特定情况下

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

在那种特定情况下,callFunc可以是这样的:

function callFunc(fn: FuncTypes, ...args: any[]) {
    return <Promise<string>>Promise.resolve(fn.call(this, ...args));
}

如果fn返回一个promise,则promise fromPromise.resolve将被解析为promise 返回的promise fn(它会等待那个promise 结算并以同样的方式结算);如果没有,您将获得一个已履行的承诺,其返回值是fn作为其分辨率值。

一般情况下

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

不是在运行时,除非您以某种方式对它们进行注释(稍后会更多)。TypeScript 的类型信息只是编译时的。

或者我应该为每种类型编写两个函数?

这可能是最好的。

您可以注释函数,例如通过在它们上放置一个属性来指示它们的返回类型是什么:

function delay(ms: number, value: string): Promise<string> {
    return new Promise<string>(resolve => setTimeout(resolve, ms, value));
}
(<any>delay).returnValue = "Promise<string>";

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

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


推荐阅读