我有一个带有一些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();
没有幻想:智能感知向我展示了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
-不能,而且无论如何,我希望它能更深入地工作。
有可能吗?
//已添加 谢谢,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
答案 0 :(得分: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;
...