首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >泛型“keyof`”中的类型记录混淆扩展了keyof`` `typeof`‘和其他

泛型“keyof`”中的类型记录混淆扩展了keyof`` `typeof`‘和其他
EN

Stack Overflow用户
提问于 2018-04-11 07:44:56
回答 1查看 4.9K关注 0票数 8
代码语言:javascript
复制
class Car {
    engine:number;
    detials:{
        good:'Boy'
    }
}

ModelProperty<T>在使用new ModelProperty<Car>('engine',22);构造时应该工作,因为engineCar的属性,22engine的类型相同,即number

代码语言:javascript
复制
export class ModelProperty<T, P extends keyof T, V  = T[P]> {
    constructor(public name: P, public value: V) { }
    fun(t: T){
        let value: any = t[this.name]; // Should not be any
        let valueWhyError: V = t[this.name]; //Error.. Why?
    }
}
let engine2 = new ModelProperty<Car,'engine'>('engine','22'); // Gives error as '22' should be number.. working great.
let engine1 = new ModelProperty<Car,'engine'>('engine',2); // But there is repeatation 'engine', 'engine'
  1. engine的情况下,V应该是指number。但是函数do中的这一行会产生错误。
  2. 构造函数不应该是<Car,'engine'>,而应该是<Car>。它的下列属性在默认情况下应取决于参数。
  3. 如何使它对嵌套属性(如new ModelProperty<Car>(['details','good'],'Girl') )起作用。
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-11 08:10:35

对于第一个问题,V参数的方法的问题是为它指定默认值,但这并不意味着V必须扩展T[P],只是默认情况下,您可以使用V的任何类型参数调用构造函数。只要在适当的地方使用T[P],就好像您正确地约束了它(V extends T[P] = T[P])编译器一样,它仍然无法正确地遵循V是从T[P]分配的。

代码语言:javascript
复制
export class ModelProperty<T, P extends keyof T> {
    constructor(public name: P, public value: T[P]) { }
    fun(t: T){
        let value = t[this.name]; // is T[P]
    }
}

至于第二个重复问题,这是类型参数和推理工作方式的一个不幸的副作用,如果您为泛型参数指定默认值,则将使用默认值,而不会进行任何推断。如果不为K指定默认值,则不能仅指定T的值,还必须指定K。简单的解决办法是使用两种函数方法:

代码语言:javascript
复制
export class ModelProperty<T, P extends keyof T> {
    constructor(public name: P, public value: T[P]) { }

    static for<T>() {
        return function <P extends keyof T>(name: P, value: T[P]){
            new ModelProperty<T, P>(name, value);
        } 
    }
}
const carModelCreator = ModelProperty.for<Car>();
let engine2 = carModelCreator('engine','22'); // Gives error as '22' should be number.. working great.
let engine1 = carModelCreator('engine',2); // But there is repeatation 'engine', 'engine'

至于嵌套路径的第三个问题,类不能有可变数量的类型参数,因此您可以选择为每个路径长度创建专用类。

代码语言:javascript
复制
export class ModelProperty2<T, P extends keyof T,  P2 extends keyof T[P]> {
    constructor(public name: [P, P2], public value: T[P][P2]) { }

    static for<T>() {
        return function <P extends keyof T, P2 extends keyof T[P]>(name: [P, P2],  value: T[P][P2]){
            new ModelProperty2<T, P, P2>(name, value);
        } 
    }
}
const carModelCreator = ModelProperty2.for<Car>();
let engine2 = carModelCreator(['detials', 'good'],'22'); //error 
let engine2 = carModelCreator(['detials', 'good'],'Boy'); //ok

或者,如果需要,可以创建一个返回实例ModelProperty的重载函数,其中唯一的类型参数是最后一个属性值,路径是string[]。在创建实例时获得类型安全性,但信息在创建后丢失。

代码语言:javascript
复制
export class ModelProperty<T, V> {
    constructor(public name: string[], public value: V) { }


    static for<T>() {
        function helper<P extends keyof T, P2 extends keyof T[P]>(name: [P, P2],  value: T[P][P2])
        function helper<P extends keyof T>(name: [P],  value: T[P])
        function helper(name: string[],  value: any){
            return new ModelProperty<T, any>(name, value);
        } 

        return helper;
    }
}
const carModelCreator = ModelProperty.for<Car>();
let engine1 = carModelCreator(['engine'], 22); // ok
let engine2 = carModelCreator(['detials', 'good'],'Boy'); //ok
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49769314

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档