typescript :函数返回类型取决于输入函数返回类型

标签 typescript generics type-inference

我有一个函数接受另一个函数的参数。 我想返回一个由传入参数的函数的返回类型配置的通用接口(interface)。

function doSomething <T>(values: Whatever[], getter: (whatever: Whatever) => T): T[] {
  return values.map(value => getter(value));
}

然后我想使 getter 函数成为可选的,并为此函数使用默认值。问题发生在那个时候。

function doSomething <T>(values: Whatever[], getter: (whatever: Whatever) => T = val => val): T[] {
  return values.map(value => getter(value));
}

所以现在我收到错误消息:

Error:(18, 47) TS2322: Type '(val: Whatever) => Whatever' is not assignable to type '(whatever: Whatever) => T'. Type 'Whatever' is not assignable to type 'T'.

你知道我为什么会收到这个错误吗?

提前谢谢你,

(下面的示例不是我的真实代码,但这更清楚地描述了我的问题)

我正在使用 typescript 2.7.2

最佳答案

问题是默认getter函数的返回类型是Whatever,但是doSomething声明要求getter必须返回TT 是泛型类型参数,可以是任何类型,不保证WhateverT 兼容。 TypeScript 编译器看不到当提供默认值时,T 不是必需的并且 doSomething 的返回类型是 Whatever[]。但是你可以用 doSomething 的这些重载声明来表达它:

function doSomething<T>(values: Whatever[], getter: (whatever: Whatever) => T): T[];
function doSomething(values: Whatever[]): Whatever[];
// the implementation must be compatible with both variants
function doSomething<T>(values: Whatever[], getter: (whatever: Whatever) => T | Whatever = val => val ): (T | Whatever)[] {
  return values.map(value => getter(value));
}

更新以解决已澄清的问题:

I wanted to avoid to return "Whatever | T" because everytime I will call this function I will have to check the response type (Whatever or T).

当您调用此函数时,仅考虑两个重载签名,TypeScript 在 doSomething() 的调用点进行重载解析时不使用实现签名。事实上,实现返回类型可以简单地声明为 any,就像在重载 documentation examples 中所做的那样。 - 它仅用于对实现进行类型检查,并且实现通常很明显,因此更严格的类型不会在那里提供太多好处。

I would like to write code to take the return type on the getter function and use as T.

如果在调用doSomething 时省略泛型参数,编译器将从getter 返回类型推断T。我认为以下示例可以满足您的要求:

interface Whatever { w: string };

function doSomething<T>(values: Whatever[], getter: (whatever: Whatever) => T): T[];
function doSomething(values: Whatever[]): Whatever[];
function doSomething<T>(values: Whatever[], getter: (whatever: Whatever) => T | Whatever = val => val ): (T | Whatever)[] {
  return values.map(value => getter(value));
}

function example() {
    const getter1 = (whatever: Whatever) => whatever.w; // returns string
    const getter2 = (whatever: Whatever) => whatever.w.length; // returns number

    const values: Whatever[] = [];

    const r0 = doSomething(values); // const r1: Whatever[]
    const r1 = doSomething(values, getter1); // const r1: string[]
    const r2 = doSomething(values, getter2); // const r2: number[]
}

关于 typescript :函数返回类型取决于输入函数返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51100363/

相关文章:

typescript - 如何通过 TypeScript 中的映射类型删除属性

angularjs - Angular 2 - @Input 不更新 super 组件上的模型

html - 滚动时顶部导航栏应该改变吗?

c# - 使用通用参数而不是显式调用构造函数

delphi - 为什么 Delphi 无法推断参数 TEnumerable<T> 的类型?

swift - 为什么 Swift 中的类型推断不处理传递约束?

haskell - 为什么这些 Haskell 函数的推断类型不完全相同?

javascript - 如何更改图像的src

java - 强制通用类型成为接口(interface)?

java - 如何通过泛型使子类型元素需要特定的子类型访问者,从而使访问者模式更具可扩展性?