Typescript 索引多态性“;这";使用类型的筛选键键入
关于为什么以下代码似乎没有使用ts版本4.2.3编译,您有什么想法吗Typescript 索引多态性“;这";使用类型的筛选键键入,typescript,Typescript,关于为什么以下代码似乎没有使用ts版本4.2.3编译,您有什么想法吗 type numberskies=keyof{ //键,其中键是字符串,键的值是数字 [K在T[K]扩展数字时输入T的键?(K扩展字符串?K:从不):从不):T[K] }; 类基类{ printNumberKey(属性:数字键){ 控制台日志(道具) } //为什么这不起作用? printNumberValuePlusOne(属性:数字键){ console.log(此[prop]+1) } //还是这个? getNumber
type numberskies=keyof{
//键,其中键是字符串,键的值是数字
[K在T[K]扩展数字时输入T的键?(K扩展字符串?K:从不):从不):T[K]
};
类基类{
printNumberKey(属性:数字键){
控制台日志(道具)
}
//为什么这不起作用?
printNumberValuePlusOne(属性:数字键){
console.log(此[prop]+1)
}
//还是这个?
getNumber(道具:T){
归还这个[道具];
}
//但这是真的吗?
getProperty(prop:T):这个[T]{
归还这个[道具];
}
}
类DerivedClass扩展了基类{
stringProp:string='';
numberProp:number=0;
1:编号;
}
让实例=新的DerivedClass();
printNumberKey('numberProp');
printNumberValuePlusOne('numberProp');
log(instance.getNumber('numberProp');
//下面应该是一个错误
//printNumberKey('stringProp');
//printNumberValuePlusOne('stringProp');
//log(instance.getNumber('stringProp');
//例如,printNumberKey(1);
//实例.printNumberValuePlusOne(1);
//log(instance.getNumber(1));
我希望能够使用prop参数索引到“this”,但编译器似乎无法理解numberkey是“this”的键。有没有一种不同的方法来过滤键值,以便编译器理解我试图做什么
这是
编辑:编辑示例以删除下面注释中提到的问题,您可以将其视为隐式类型参数。在基类
的主体内,此
类型未指定;编译器只知道这扩展了基类。只有在创建实例时,this
才会隐式指定为实例的类型
TypeScript编译器并不特别擅长对依赖于尚未指定的泛型类型参数的类型进行推理;特别是当这些类型类似于正在进行的内部数字键
时。一般来说,编译器只会推迟对这些类型的求值,而无法验证是否有任何特定的值可分配给它们
这是Typescript的设计限制。我不确定是否有关于这方面的规范性文档,但您可以查看类似于或的问题,这些问题被标记为这样,因为编译器无法执行验证这一点所需的分析
所以你必须解决这个问题。最简单的方法是使用a来告诉编译器此[prop]
的类型是什么,因为它无法识别:
printNumberValuePlusOneAssert(prop: NumbersKeys<this>) {
console.log(this[prop] as unknown as number + 1)
}
现在没有错误了。如果此
类型为记录
,则编译器会将数字键
类型的索引视为数字
。您甚至可以在这里获得某种类型的安全性,尽管这不是您所期望的。在对实例调用该方法之前,不会真正检查该
参数。如果实例的类型与此
参数匹配,则调用将编译为无错误:
instance.enforcedLater("numberProp"); // okay
否则,您将在实例上收到警告。很难证明这一点,因为在prop
isNumberKeys
中已经禁止了坏键。如果您将其更改为以下内容:
enforcedLater<K extends keyof this>(
this: Record<K, number>,
prop: K
) {
console.log(this[prop] + 1);
}
enforcedLater(
这:记录,,
道具:K
) {
控制台日志(此[prop]+1);
}
您可以在实例本身上看到错误:
instance.enforcedLater("numberProp"); // okay
instance.enforcedLater("stringProp"); // error!
//~~~~~~ <-- Types of property 'stringProp' are incompatible.
instance.enforcedLater(“numberProp”);//可以
instance.enforcedLater(“stringProp”);//错误!
//~~~~~您使用的是文本字符串'never'
,而不是never
。这是一个小小的改进:type NumbersKeys={[K in Extract]:T[K]扩展了数字?K:never;}[Extract]
但是它仍然没有得到This[NumberKeys]
是number
。谢谢!编辑示例。它还不明白NumberKeys可以用来索引这个。我建议的代码允许你毫无问题地访问这个[prop]
,但它仍然有错误,因为它不明白这个[prop]
总是数字这并不能回答你的问题,但是你的NumberKeys
类型相当复杂;一个更简单的实现是{[K in keyof T]:T[K]扩展了number?K:never}[keyof T]&string
。非常有用,非常彻底,谢谢!由于类型安全性,将使用第二个选项,而ts错误似乎最有帮助
instance.enforcedLater("numberProp"); // okay
instance.enforcedLater("stringProp"); // error!
//~~~~~~ <-- Types of property 'stringProp' are incompatible.