我写了一个更新函数,它接受一个对象,T
,以及一个“更新程序”对象,它采用与以下相同的键(或子集)T
并提供更新原对象对应值的函数。
type UpdaterObj<T> = {
[K in keyof Partial<T>]: (t: T[K]) => T[K]
};
declare function update<T>(obj: T, updaterObj: UpdaterObj<T>): T
示例用法如下:
const foo = {
x: 1,
y: "1"
};
update(foo, {
x: (xx: number) => xx + xx,
y: (yy: string) => yy + yy,
}); // Result is { x: 2, y: "11" }
这可行,但我真的想删除这些注释并只写x: (xx) => xx + xx
and y: (yy) => yy + yy
,但是我得到了Parameter implicitly has type 'any'
错误,对于两者xx
and yy
.
这很奇怪,因为如果我将鼠标悬停在x:
,它正确地推断出相应的值应该是什么,但是,如果我注释它它会抱怨xx
or yy
作为错误的类型,而且我很确定我以前见过打字稿做出类似的推论。
在这种情况下,注释非常简单,但如果我深入对象或更复杂的类型,注释可能会变得烦人,因此推理在这里非常有帮助。
对我的定义或用法是否有任何简单的调整,可以让打字稿为我推断这一点?
我不确定是否存在问题GitHub关于函数参数的类型推断如何与泛型类型参数的推断交互,所以我不知道是否对函数签名进行了简单的调整,使其可以在不影响调用站点的情况下工作。
看着TypeScript 规范,我看到对于 TypeScript 函数表达式(例如xx => xx + xx
),
当没有类型参数且没有参数类型注释的函数表达式由类型根据上下文类型化时T
和上下文签名S
可以从中提取T
,函数表达式的处理就好像它具有显式指定的参数类型注释一样,因为它们存在于S
.
[snip]
上下文签名S
从函数类型中提取T
如下:
所以看起来好像是因为(xx => xx + xx
)在您的原始调用中具有以下形式的函数类型(t: T['x']) => T['x']
包括类型参数T
,它不会像处理具有显式类型参数那样处理该函数。据推测,这意味着编译器在消除通用参数之前尝试提取上下文签名。
如果可以更改调用站点,那么我可以提出的最简单的建议(明显有效)就是打破两个参数update()
函数变成curried函数如下:
declare function updateCurried<T>(obj: T): (updaterObj: UpdaterObj<T>) => T
其使用方式如下(注意函数调用的顺序):
updateCurried(foo)({
x: xx => xx + xx,
y: yy => yy + yy,
}); // okay
这实质上迫使编译器在评估泛型类型参数时评估并消除泛型类型参数。updaterObj
prarameter,此时它可以进行上下文函数参数推断,如上面规范摘录中所述。
希望这对您有帮助。祝你好运!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)