程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了使用过滤的 keyof 类型索引多态“this”类型大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决使用过滤的 keyof 类型索引多态“this”类型?

开发过程中遇到使用过滤的 keyof 类型索引多态“this”类型的问题如何解决?下面主要结合日常开发的经验,给出你关于使用过滤的 keyof 类型索引多态“this”类型的解决方法建议,希望对你解决使用过滤的 keyof 类型索引多态“this”类型有所启发或帮助;

有关为什么以下代码似乎无法使用 ts 4.2.3 版进行编译的任何想法:

type numbersKeys<T extends BaseClass> = keyof {
    // Keys where key is a String and value of key is a number
    [K in keyof T as T[K] extends number ? (K extends String ? K : never) : never]: T[K]
};

class BaseClass {
    printnumberKey(prop: numbersKeys<this>){
        console.log(prop)
    }
    // Why doesnt this work?
    printnumberValuePlusOne(prop: numbersKeys<this>) {
        console.log(this[prop] + 1)
    }
    // Or this?
    getnumber<T extends numbersKeys<this>,K extends this[T]>(prop: T) {
        return this[prop]; 
    }
    // But this does?
    getProperty<T extends keyof this>(prop: T): this[T] {
        return this[prop]; 
    }
}

class DerivedClass extends BaseClass {
    StringProp: String = '';
    numberProp: number = 0;
    1: number;
}

let instance = new DerivedClass();

instance.printnumberKey('numberProp');
instance.printnumberValuePlusOne('numberProp');
console.log(instance.getnumber('numberProp'));

// Below should error

// instance.printnumberKey('StringProp');
// instance.printnumberValuePlusOne('StringProp');
// console.log(instance.getnumber('StringProp'));

// instance.printnumberKey(1);
// instance.printnumberValuePlusOne(1);
// console.log(instance.getnumber(1));

我希望能够使用 prop 参数来索引“this”,但编译器似乎无法理解 numberKeys 是“this”的键。是否有不同的方法来过滤 keyof 值,以便编译器了解我正在尝试做什么?

这是a link to the typescript playground example of this:

编辑:编辑示例以删除下面评论中提到的问题

解决方法

您可以将 polymorphic this type 视为隐式 generic 类型参数。在 BaseClass 的主体内部,未指定 this 类型;编译器只知道 this extends BaseClass。只有当您创建实例时,this 才被隐式指定为实例的类型。

而且 TypeScript 编译器并不是特别擅长推理依赖于尚未指定的泛型类型参数的类型;尤其是当这些类型是 conditional types 时,例如 numbersKeys 中的 key remapping。一般而言,编译器只会延迟评估这些类型,并且无法验证是否可以为它们分配任何特定值。

这是 Typescript 的设计限制。我不确定是否有关于此的规范文档,但您可以查看诸如 microsoft/TypeScript#30728 或 microsoft/TypeScript#42896 之类的问题,这些问题已被标记为此类问题,因为编译器无法执行必要的分析来验证这一点。


所以你必须解决它。最简单的方法是使用 type assertion 告诉编译器 this[prop] 的类型是什么,因为它无法弄清楚:

printnumberValuePlusOneAssert(prop: numbersKeys<this>) {
    console.log(this[prop] as unknown as number + 1)
}

这会将维护类型安全的负担从编译器转移到您身上,所以要小心;你可以写this[prop] as unknown as String,它不会抱怨。


另一种解决方法是给 printnumberValuePlusOne() 一个 this parameter 类型,其中编译器可以验证 this[prop]number

printnumberValuePlusOne(
    this: Record<numbersKeys<this>,number>,prop: numbersKeys<this>
) {
    console.log(this[prop] + 1)
}

现在没有错误。如果 this 的类型为 Record<numbersKeys<this>,number>,则编译器认为使用 numbersKeys<this> 类型的键对其进行索引是 number。您甚至可以在这里获得某种类型安全性,尽管不是您所期望的。在对实例调用方法之前,不会真正检查 this 参数。如果实例的类型与 this 参数匹配,则调用将编译而不会出错:

instance.enforcedLater("numberProp"); // okay

否则,您将收到有关实例的警告。很难证明这种情况发生,因为您已经禁止坏键,因为 propnumberKeys<this>。如果您将其更改为以下内容:

enforcedLater<K extends keyof this>(
    this: Record<K,prop: K
) {
    console.log(this[prop] + 1);
}

您可以在实例本身上看到错误:

instance.enforcedLater("numberProp"); // okay
instance.enforcedLater("StringProp"); // error!
//~~~~~~ <-- Types of property 'StringProp' are incompatible.

Playground link to code

大佬总结

以上是大佬教程为你收集整理的使用过滤的 keyof 类型索引多态“this”类型全部内容,希望文章能够帮你解决使用过滤的 keyof 类型索引多态“this”类型所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:keyof