如何从Typescript中的函数返回正确的类型?

时间:2017-07-29 21:14:06

标签: typescript

我有以下界面:

interface Functor<T> {
  map <T1>(f: (x: T) => T1): Functor<T1>
}


interface Maybe<T> extends Functor<T> {}

接下来,我有map函数实现,它需要Functor并调用它.map方法:

function map<T, U>(f: (x: T) => U, a: Functor<T>): Functor<U>

function map(f, a) {
  return a.map(f);
}

如果我将此map函数与Maybe一起使用,则返回类型将为Functor<T>而不是Maybe<T>

// type is Maybe<number>
const mb = new Just(5);

// type is Functor<string>, but should be Maybe<string>
const result = map((x) => 'str', mb)

我可以通过向map函数添加额外的重载来解决这个问题:

function map<T, U>(f: (x: T) => U, a: Maybe<T>): Maybe<U>

但问题是FunctorMaybe类型位于不同的npm包中,map函数实现对Maybe一无所知。

我怎么能实现这个目标?

1 个答案:

答案 0 :(得分:2)

TypeScript当前(截至2.4)缺少higher kinded types,这正是您正确表达a参数与返回值之间关系所需的内容。例如,如果TypeScript允许泛型类型参数本身是通用的,您可以这样说:

function map<T, U, F<X> extends Functor<X>>(f: (x: T) => U, a: F<T>): F<U> {...}

(使用我刚编写的F<X>符号)或:

function map<T, U, F extends Functor>(f: (x: T) => U, a: F<T>): F<U> {...}

(以您目前无法做到的方式使用裸Functor)。

然后编译器可能会自动推断Maybe的{​​{1}}。

如果您认为自己的用例足够引人注目,则可能需要转到the relevant GitHub issue,并通过提供或至少提供顶级帖子来表明您的支持。

正如@Stephan指出的那样,实际上并没有比你目前所做的更好的解决方法。我偶尔尝试用非语言足够的语言实现仿函数等,最终会转变为手动类型注释和未经检查的类型断言。我主要建议放弃☹️并仅实现您需要的特定仿函数,而不是试图对它们进行抽象。

希望有所帮助。祝你好运。