Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript使用受该值类型约束的键访问泛型类型的值_Typescript_Typescript Generics - Fatal编程技术网

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 `

我有一个typescript函数,它接受泛型类型和该泛型类型的键。我约束该键,以便函数只接受值为特定类型的键。当使用受约束键访问泛型对象时,我不会得到预期的返回类型

如何将泛型对象的键约束为特定的值类型,并在泛型函数中访问该值

例如:

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来告诉编译器它无法理解的内容:that
shouldbeadate,但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()
}