Typescript使用受该值类型约束的键访问泛型类型的值
我有一个typescript函数,它接受泛型类型和该泛型类型的键。我约束该键,以便函数只接受值为特定类型的键。当使用受约束键访问泛型对象时,我不会得到预期的返回类型 如何将泛型对象的键约束为特定的值类型,并在泛型函数中访问该值 例如:Typescript使用受该值类型约束的键访问泛型类型的值,typescript,typescript-generics,Typescript,Typescript Generics,我有一个typescript函数,它接受泛型类型和该泛型类型的键。我约束该键,以便函数只接受值为特定类型的键。当使用受约束键访问泛型对象时,我不会得到预期的返回类型 如何将泛型对象的键约束为特定的值类型,并在泛型函数中访问该值 例如: function onlyTakesADateKey<T, K extends keyof T>(item: T, key: T[K] extends Date ? K : never): void { //I've constrained `
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")
函数onlyTakesDateKey(项:T,项:T[K]扩展日期?K:从不):无效{
//我约束了'key',以确保项[key]是一个日期,但它不会被键入为日期
常量shouldBeADateButIsNot=项[键]
//类型“T[T[K]扩展日期?K:从不]”上不存在属性“getTime”。ts(2339)
应该是date但不是。getTime()
}
const foo={key1:“asdf”,key2:new Date()}
//“string”类型的参数不能分配给“never”类型的参数。ts(2345)
常数条=仅TakesDateKey(foo,“键1”)
//它正确地约束了键,但根据上文,无法访问函数中的日期值
const baz=onlyTakesADateKey(foo,“key2”)
为什么
不应该是日期而不是日期?关键点已被正确约束。我无法向函数传递导致它不是日期的参数。编译器无法真正处理这一问题,这取决于onlyTakesADateKey
实现中尚未指定的类型参数,如t
和K
。在函数实现内部,类型T[K]的评估是否会延长日期?K:从不
被推迟。这就是为什么您会看到关于T[T[K]延长日期的错误?K:从不]
。编译器无法进行必要的高阶推理,从而得出结论,即它必须可分配给日期
。这是TypeScript的设计限制,如中所示
编译器通常会推迟对依赖于未指定泛型的类型的求值,但也有一些地方可以做得更好。一个是:如果您有一个类型为Record
的值,并使用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 bar = onlyTakesADateKey(foo, "key1"); // error!
// -------------------------> ~~~
// Types of property 'key1' are incompatible.
如果您真的不想更改有关调用的任何内容,则始终可以使用a来告诉编译器它无法理解的内容:thatshouldbeadate,但that
是日期
:
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()
}
函数仅限TakesDateKeyOrig(
项目:T,键:T[K]延长日期?K:从不):无效{
const shouldBeADateButIsNot=item[key]作为任意日期;
应该是date但不是。getTime()
}
很有趣,谢谢你的精彩解释!
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()
}