![](/img/trans.png)
[英]How can I create an object in TypeScript with a constrained generic value type?
[英]Typescript access value of generic type using key constrained by the type of that value
我有一个 typescript function ,它采用泛型类型和该泛型类型的键。 我限制该键,以便 function 将仅接受其值属于某种类型的键。 当使用约束键访问通用 object 时,我没有得到预期的类型作为回报。
如何将通用 object 的键约束为特定值类型并在通用 function 中访问该值?
例如:
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
? 密钥被适当地约束。 我无法将 arguments 传递给 function 导致它不是日期。
在onlyTakesADateKey
的实现中,编译器无法真正处理依赖于尚未指定的泛型类型参数(如T
和K
)的条件类型。 在 function 实现中,评估类型T[K] extends Date? K: never
T[K] extends Date? K: never
推迟。 这就是为什么您会看到有关T[T[K] extends Date? K: never]
T[T[K] extends Date? K: never]
。 编译器无法进行必要的高阶推理来得出结论,它必须可以分配给Date
。 这是 TypeScript 的设计限制,如microsoft/TypeScript#30728 所示。
编译器通常会推迟对依赖于未指定 generics 的类型的评估,但在一些地方它可以做得更好。 一种是:如果您有一个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.
如果您真的不想更改有关调用的任何内容,则始终可以使用类型断言来告诉编译器它无法弄清楚的内容: 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()
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.