如何覆盖对象字段并让IDE看到它?

问题描述 投票:0回答:1

我有一些带有一些State属性的类,我通过一些函数格式化State的字段:

function DoMagic(prototypeObj: any) : any;

因此,功能“DoMagic”将对象变为:

const Foo = {
    ID: -1,
    Name: '',
    Something: [1,2,3]
}

const Bar = {
    ID: {
        get Value(){return Foo.ID;},
    },
    Name: {
        get Value(){return Foo.ID;},
    },
    Something: {
        0: {get Value(){return Foo.Something[0]} },
        1: {get Value(){return Foo.Something[1]} },
        2: {get Value(){return Foo.Something[2]} },
    }
};

它运行正常,但是当Foo是类属性时,我想让WebStorm的自动完成提供Bar的属性而不是Foo。

如果我做的事情

type ClassState = {
    ID: number;
    Name: string;
    Something: number[]
}
class Class1{
    State: ClassState = {
        ID: -1,
        Name: '',
        Something: [1,2,3],
    };
    constructor(){
        Object.defineProperty(this, 'State', DoMagic(this.State))
    }
}
let instance = new Class1();

并没有错觉:当然,intellisense会向我展示ClassState的属性。

我得到它的最接近的方式 - 定义一些自定义类型并声明自己的“接口”,如下所示:

class TypesBase {
    protected _Value: any;
    get Value():any {return this._Value};
}
class TypeInt extends TypesBase{
    get Value() : number {return this._Value};
}
class TypeString extends TypesBase{
    get Value() : string {return this._Value};
}
class TypeArray<T> extends TypesBase{
    get Value() : T[] {return this._Value};
}
class Class2 {
    State = {
        ID: new TypeInt(),
        Name: new TypeString(),
        Something: new TypeArray<number>(),
    };
    StateData = {
        ID: -1,
        Name: '',
        Something: [1,2,3],
    };
    constructor(){
        Object.defineProperty(this, 'State', DoMagic(this.StateData))
    }
}
let inst2 = new Class2();

它适用于像inst2.ID.Value这样的简单字段,但inst2.Something[0].Value - 没有,而且,无论如何,我希望它能更深入地工作。

有可能吗?

// ADDED谢谢,jcalz,这种方式更清洁

type Magic<T> = {[K in keyof T]: any | {Value: T[K]}};
class Class2 {
    State: Magic<ClassState> = {
        ID: -1,
        Name: '',
        Something: [1,2,3],
    };
...

但是如何让它更深层次?喜欢:

inst2.Something[0].Value
inst2.Something[0].DeeperLevelObject.Value
javascript typescript autocomplete webstorm
1个回答
0
投票

问题解决了。

需要声明类型:

type Simple<T> = {Value: T};
type MagicArray<T, U> = {
    [Key: number]: Simple<U>;
    Value: T
}

type Magic<T> = Simple<T>
    &
    {   readonly [K in keyof T]:
            T[K] extends (infer ElementType)[] ? MagicArray<T[K], ElementType>:
            T[K] extends object ? Magic<T[K]> :
            Simple<T[K]>
    }

使用:

type ClassState2 = {
    Field1: number;
    Field2: string;
};
type ClassState = {
    ID: number;
    Name: string;
    SomeArr: number[];
    SomeObj: ClassState2;
    SomeObjArr: ClassState2[];
};

const SomeState : Magic<ClassState> = null;

//now SomeState can get autocomplete with proper types:
SomeState.Value; 
SomeState.ID.Value;
SomeState.SomeArr[0].Value;
SomeState.SomeObjArr[0].Field1.Value;
...
© www.soinside.com 2019 - 2024. All rights reserved.