从概念上讲,考虑到你的Dates
定义,你可以这样写:
function doSomething<T>(inst: T, key: keyof Dates<T>) {
const date = inst[key];
date?.getdate(); // error
}
但不幸的是,TypeScrip不能"看到"inst[key]
是可以赋值给Date | undefined
的类型,即使Dates
的定义暗示了这一点.TypeScrip缺少"可赋值给类型V
的T
的属性"形式的本机操作符.我通常将其称为KeysMatching<T, V>
,其中KeysMatching<T, Date | undefined>
相当于您的代码的keyof Dates<T>
.当然,您可以定义在某些情况下可以工作的您自己的版本,但是当T
是泛型时,编译器不能遵循逻辑.在microsoft/TypeScript#48992处有一个开放的特性请求,以本地支持KeysMatching
,但目前它不是语言的一部分,您需要解决它.
我能设想的最小解决办法是以这种方式将T
转换为constrain,这样TypeScrip就知道T[keyof Dates<T>]
是Date | undefined
的子类型.例如,如下所示:
function doSomething<
T extends Record<keyof Dates<T>, Date | undefined>,
>(inst: T, key: keyof Dates<T>) {
const date = inst[key];
date?.getDate() // okay
}
这正如广告所说的那样奏效.让我们来测试一下:
const v = { a: "abc", b: new Date(), c: undefined, d: 123 };
doSomething(v, "b"); // okay
doSomething(v, "c"); // okay
doSomething(v, "a"); // error!
// Argument of type '"a"' is not assignable to parameter of type '"b" | "c"'
看上go 不错!
Playground link to code个