[英]Why does this snippet allow Typescript to infer a generic from a "parent" function?
似乎有一个未记录的功能允许函数从 function 推断类型,其中它们作为参数传递。
我试图了解为什么会这样,以及是否是故意的。
给定一个Model
,然后使用通用update
并apply
function,当使用update
的结果作为参数时,我可以从apply
中推断出一个类型,技巧T extends infer U? U: never
T extends infer U? U: never
:
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
签名中使用 DontInfer 时,不会推断T
的使用位置。 在我的示例中,可以说通用参数u
的形状为Partial<T>
,但T
不会由u
推断:
function update<T>(u: DontInfer<Partial<T>>) { return (t: T) => ({ ...t, ...(u as Partial<T>) }) };
这意味着如果单独使用update
function 将无法推断T
:
// T is inferred to be `unknown`
update({ foo: 1 })
但是当在上下文中使用时,可以推断出 T:
// T is inferred to be Model
setState<Model>(update({ foo: 1 }));
DontInfer
用于此目的是因为它推迟评估未解决的条件类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.