泛型类型的TypeScrip访问值使用由该值的类型约束的键 [英] Typescript access value of generic type using key constrained by the type of that value
本文介绍了泛型类型的TypeScrip访问值使用由该值的类型约束的键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
如何将泛型对象的键约束为特定值类型并在泛型函数中访问该值?
例如:
function onlyTakesADateKey<T, K extends keyof T>(item: T, key: T[K] extends Date ? K : never): void {
//I've constrained `key` to ensure that item[key] is a Date but this doesn't get typed as a Date
const shouldBeADateButIsNot = item[key]
//Property 'getTime' does not exist on type 'T[T[K] extends Date ? K : never]'.ts(2339)
shouldBeADateButIsNot.getTime()
}
const foo = { key1: "asdf", key2: new Date() }
//Argument of type 'string' is not assignable to parameter of type 'never'.ts(2345)
const bar = onlyTakesADateKey(foo, "key1")
//It properly constrains the key, but per above can't access the date value in the function
const baz = onlyTakesADateKey(foo, "key2")
为什么shouldBeADateButIsNot
不是Date
?该关键点受到适当的约束。我无法将参数传递给导致不是为日期的函数。
推荐答案
编译器实际上无法处理依赖于onlyTakesADateKey
实现中尚未指定的T
和K
等类型参数的conditional types。在函数实现内部,T[K] extends Date ? K : never
类型的计算是延迟的。这就是为什么您会看到关于T[T[K] extends Date ? K : never]
的错误。编译器无法进行必要的高阶推理,从而得出结论:它必须可赋值给Date
。这是打字稿的设计限制,可以在microsoft/TypeScript#30728中看到。
编译器通常会推迟对依赖于未指定泛型的类型的求值,但也有一些地方可以做得更好。一种是:如果您有一个Record<K, V>
类型的值,并用K
对其进行索引,编译器将理解它是V
类型。因此,泛型查找并不总是完全延迟的。这建议重写T
和K
约束,如下所示:
function onlyTakesADateKey<T extends Record<K, Date>, K extends PropertyKey>(
item: T, key: K): void {
const isActuallyADateNow = item[key]
isActuallyADateNow.getTime()
}
这是没有错误的,并且您的示例行为类似:
const foo = { key1: "asdf", key2: new Date() }
const baz = onlyTakesADateKey(foo, "key2"); // okay
有一个明显的例外,即当您出错时,编译器会抱怨item
而不是key
:
const bar = onlyTakesADateKey(foo, "key1"); // error!
// -------------------------> ~~~
// Types of property 'key1' are incompatible.
如果您真的不想更改调用的任何内容,您总是可以使用type assertion只告诉编译器它不能弄明白的:shouldBeADateButIsNot
是Date
:
function onlyTakesADateKeyOrig<T, K extends keyof T>(
item: T, key: T[K] extends Date ? K : never): void {
const shouldBeADateButIsNot = item[key] as any as Date;
shouldBeADateButIsNot.getTime()
}
这篇关于泛型类型的TypeScrip访问值使用由该值的类型约束的键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文