似乎有一个未记录的功能,它允许函数从作为参数传递的函数中推断出类型。
我试图理解为什么会这样,以及它是否是有意为之。
给定一个 Model
,然后使用通用的 update
和 apply
函数,我可以从 apply
推断出类型> 当使用 update
的结果作为参数时,使用技巧 T extends infer U ? U:从不
:
interface Model {
foo: number
bar: string
}
function apply<T>(fn: (t: T) => T) {};
function whyDoesThisWork() {
function update<T>(u: T extends infer U ? Partial<U> : never) { return (t: T) => ({ ...t, ...u }) };
// Somehow, Typescript is able to infer that we want Model to be the generic supplied for update
apply<Model>(update({ foo: 1 }));
}
function thisDoesntWorkForObviousReasons() {
function update<T>(u: Partial<T>) { return (t: T) => ({ ...t, ...u }) }
// update infers T as { foo: 1 }, because that makes sense
apply<Model>(update({ foo: 1 }));
}
最佳答案
出现此行为的原因是 Contextual Typing .
可以将“技巧”提取到名为 DontInfer
的帮助程序中:
type DontInfer<T> = T extends infer S ? S : never;
何时 DontInfer
用于通用函数签名, T
不会推断它在哪里使用。在我的示例中,通用参数 u
可以说是形状Partial<T>
,但是T
u
不会推断出:
function update<T>(u: DontInfer<Partial<T>>) { return (t: T) => ({ ...t, ...(u as Partial<T>) }) };
这意味着update
函数将无法推断 T
如果单独使用:
// T is inferred to be `unknown`
update({ foo: 1 })
但是当在上下文中使用时,T 可以被推断出来:
// T is inferred to be Model
setState<Model>(update({ foo: 1 }));
DontInfer
适用于此目的,因为它 defers evaluating unresolved conditional types .
关于typescript - 为什么此代码片段允许 Typescript 从 "parent"函数推断泛型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70120188/