[英]Infer properties of object passed to class constructor (typescript)
I have the following situation:我有以下情况:
abstract class A {
obj;
constructor(obj:{[index:string]:number}) {
this.obj = obj;
}
}
class B extends A {
constructor() {
super({i:0})
}
method() {
//Here I would like intellisense to only suggest this.obj.i
}
}
class C extends A {
constructor() {
super({i:0,j:0})
}
method() {
//Here I would like intellisense to only suggest this.obj.i and this.obj.j
}
}
I would like in class B
to get autocompletion for the object passed in the constructor and likewise for class C
.我想在
class B
中自动完成在构造函数中传递的 object 和class C
Is there a way to do this, or am I doing something fundamentally wrong here?有没有办法做到这一点,还是我在这里做一些根本错误的事情?
You can try using generic
A
class like this:您可以尝试像这样使用
generic
A
class :
abstract class A<T extends Record<string, number> = Record<string, number>> {
obj: T;
constructor(obj:T) {
this.obj = obj;
}
}
class B extends A<{ i: number }> {
constructor() {
super({i:0})
}
method() {
//Here I would like intellisense to only suggest this.obj.i
}
}
class C extends A<{ i: number, j: number }> {
constructor() {
super({i:0,j:0})
}
method() {
//Here I would like intellisense to only suggest this.obj.i and this.obj.j
}
}
Playground Two ways to do this, it has to do with utilizing generics Playground有两种方法可以做到这一点,它与利用 generics 有关
abstract class A<T extends number extends infer U ? U : number> {
obj;
constructor(obj:{[index:string]:T}) {
this.obj = obj;
}
}
class B extends A<0> {
constructor(public readonly i: number extends infer U ? U : number) {
super({i:0});
this.i.valueOf() in super.obj;
/**
Inferred value when cntrl+hover super
constructor A<0>(obj: {
[index: string]: 0;
}): A<0>
*/
}
truthyMethod() {
console.log(super.obj)
const superObjEqualsObjCreate = super.obj === Object.create({ i: this.i }) ? true : false;
console.log(superObjEqualsObjCreate);
return superObjEqualsObjCreate
/**
* Here intellisense only suggests the result of i
(property) A<0>.obj: {
[index: string]: 0;
}
*/
}
}
class C extends A<3.14> {
constructor() {
super({i:3.14,j:3.14})
}
method() {
const superObjEqualsObjCreate = super.obj === this.obj ? true : false;
console.log("C: " + superObjEqualsObjCreate)
return superObjEqualsObjCreate;
//(property) A<3.14>.obj: {
// [index: string]: 3.14;
// }
}
}
This next approach is my preference, slightly more complex for the generic but a much more concise super
inference下一种方法是我的偏好,对于通用但更简洁的
super
推理稍微复杂一些
If you want to pass different values to each key in your super objects then you can use A<number>
when extending the abstract class A (otherwise they have to be constant -- a union of numbers or floats would work as well)如果您想将不同的值传递给超级对象中的每个键,则可以在扩展抽象 class A 时使用
A<number>
(否则它们必须是恒定的——数字或浮点数的联合也可以)
abstract class A<T extends number extends {[index: string]: infer U} ? U : number> {
obj;
constructor(obj:Record<string, T>) {
this.obj = obj;
}
}
class B extends A<0> {
constructor(public readonly i: number extends infer U ? U : number) {
super({i:0});
// Inferred value when cntrl+hover super
// constructor A<0>(obj: Record<string, 0>): A<0>
}
stringify() {
return JSON.stringify({
i: this.i, // i: number
sup: super.obj // sup: { [x: string]: 0; }
}, null, 2);
// Here intellisense only suggests the result of i
// (property) A<0>.obj: {
// [index: string]: 0;
// }
}
}
class C extends A<3.14 | -7.28> {
constructor() {
super({i:3.14,j:-7.28})
// super inferred:
// constructor A<3.14 | -7.28>(obj: Record<string, 3.14 | -7.28>): A<3.14 | -7.28>
}
method() {
super.obj === this.obj ? true : false;
//Here I would like intellisense to only suggest this.obj.i and this.obj.j
}
}
console.log(new B(12).stringify()); // B is dynamic, accepts args
console.log(new C()) // C is static
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.