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中有其他反直觉的推理案例,也欢迎他们提及。
答案 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
,我也明确声明了调用的泛型,输出将使用该通用值。