通用函数参数的推断

时间:2018-05-09 22:04:29

标签: typescript

TypeScript中的基本类型推断非常简单:

const bar = foo(); // bar: <type that foo returns>

考虑到泛型参数默认值为{},可以合理地预期下面的代码会导致类型错误,因为回调函数返回number而不是{}

function foo<T = {}>(callback: () => T): T {
    return callback();
}

let bar = foo(() => 1); // bar: number

但是众所周知,T是从回调返回值中推断出来的,它是:

function foo<number>(callback: () => number): number

这究竟是怎么发生的,这个行为在哪里规定?来自TypeScript开发人员的文档或解释的引用将会有所启发。

是否可以强制T为默认值({}<T = ...>中指定的任何内容),而不是foo(() => 1)来电推断?在某些情况下,这可能是理想的行为。

如果在TypeScript中有其他反直觉的推理案例,也欢迎他们提及。

1 个答案:

答案 0 :(得分:1)

在某种程度上,你回答了自己的问题:

  

考虑到通用参数默认值为{}

使用语法<T = {}>,您将分配默认值,而不是要求。仅当TypeScript无法通过其他方式推断T的类型时,才会使用默认值。

如果要明确限制T可以采用的格式,则应使用通用约束而不是默认约束。 (参见TypeScript Generics documentation

中的通用约束部分

例如,使用您提供的示例:

function foo<T extends object>(callback: () => T): T {
  return callback();
}

let bar = foo(() => 1); // Type 'number' is not assignable to type 'object'

您甚至可以使用<T extends object = {}>

在约束旁边提供默认值

至于你有些不同的问题:

  

是否可以强制T为默认值[...]而不是推断

是的,当您进行函数调用以覆盖推理时,您始终可以提供类型。例如:

function foo<T extends object = {}>(callback: () => T): T {
  return callback();
}

interface User { name: string }
const user: User = { name: 'Bob' };

let bar = foo<{}>(() => user); // bar: {}

即使我已经传递T类型User,我也明确声明了调用的泛型,输出将使用该通用值。