泛型 class 部分初始值设定项
generic class partial initializer
我有很多类似的 类,我想使用以下语法进行初始化:
class A {
b: number = 1
constructor(initializer?: Partial<A>) {
Object.assign(this, initializer)
}
}
new A({b: 2})
我认为能够通过这种方式进行初始化是一种通用行为,因此我想隔离此逻辑以避免在数十个文件中重复我自己。我试过这个:
class Initializable<T> {
constructor(initializer?: Partial<T>) {
Object.assign(this, initializer)
}
}
class A extends Initializable<A> {
b: number = 1
}
new A({b: 2})
这可以编译但不起作用,因为隐式 super()
先执行,所以 b
按需要得到 2
但随后得到 1
.
TypeScript 是否提供类型安全的解决方案来在我的所有 类 中实现此行为?
没有简单的方法可以在派生的 class 构造函数完成后从基础 class 中 运行 一些东西。我能看到的唯一解决方案(我邀请其他人提出更好的解决方案 :) )是使用一个函数来增强将成为 A
class 的函数,而不是使用基数 class.基本上是添加功能的混合方法。
function initializable<T extends new() => any>(cls: T) : {
new (data?: Partial<InstanceType<T>>) : InstanceType<T> // add the constructor
} & Pick<T, keyof T> /* add statics back */ {
return class extends (cls as any) {
constructor(data?: Partial<InstanceType<T>>){
super();
if(data) {
Object.assign(this, data);
}
}
} as any
}
const A = initializable(class {
b: number = 2;
static staticMethod() { }
method() {}
});
type A = InstanceType<typeof A> // Optionally define the type for A to have the same effect as the class
var a = new A({b:1});
console.log(a.b) // output 1
a.method();
A.staticMethod();
a = new A();
console.log(a.b) // output 2
var aErr = new A({b:"1"}); //error
注意 通常不允许混入不更改构造函数参数,这就是为什么我们必须对类型进行一些修改,但它确实有效。
我有很多类似的 类,我想使用以下语法进行初始化:
class A {
b: number = 1
constructor(initializer?: Partial<A>) {
Object.assign(this, initializer)
}
}
new A({b: 2})
我认为能够通过这种方式进行初始化是一种通用行为,因此我想隔离此逻辑以避免在数十个文件中重复我自己。我试过这个:
class Initializable<T> {
constructor(initializer?: Partial<T>) {
Object.assign(this, initializer)
}
}
class A extends Initializable<A> {
b: number = 1
}
new A({b: 2})
这可以编译但不起作用,因为隐式 super()
先执行,所以 b
按需要得到 2
但随后得到 1
.
TypeScript 是否提供类型安全的解决方案来在我的所有 类 中实现此行为?
没有简单的方法可以在派生的 class 构造函数完成后从基础 class 中 运行 一些东西。我能看到的唯一解决方案(我邀请其他人提出更好的解决方案 :) )是使用一个函数来增强将成为 A
class 的函数,而不是使用基数 class.基本上是添加功能的混合方法。
function initializable<T extends new() => any>(cls: T) : {
new (data?: Partial<InstanceType<T>>) : InstanceType<T> // add the constructor
} & Pick<T, keyof T> /* add statics back */ {
return class extends (cls as any) {
constructor(data?: Partial<InstanceType<T>>){
super();
if(data) {
Object.assign(this, data);
}
}
} as any
}
const A = initializable(class {
b: number = 2;
static staticMethod() { }
method() {}
});
type A = InstanceType<typeof A> // Optionally define the type for A to have the same effect as the class
var a = new A({b:1});
console.log(a.b) // output 1
a.method();
A.staticMethod();
a = new A();
console.log(a.b) // output 2
var aErr = new A({b:"1"}); //error
注意 通常不允许混入不更改构造函数参数,这就是为什么我们必须对类型进行一些修改,但它确实有效。