我没有看到将配置对象作为成员对象添加到类中的大问题。所有当前的解决方案在最新的Typescript版本的帮助下都不是很好,只是简化了一些简单的事情。在Combining destructuring with parameter properties之前已经提出类似的建议。这个建议已经快2年了。但是,有很多方法可以完成上述操作,我不确定的是您是否需要访问类中的字段。
走上一些方法可以帮助你解决以上,考虑到如下界面...
interface IConfigOpts {
propA: string,
propB: boolean
propC: number
}
...这类结构。
class Config {
constructor(opts: IConfigOpts) {
// Object.assign(this, opts);
Object.entries(opts).forEach((property: [string, any]) => {
Object.defineProperty(this, property[0], {
writable: true,
value: property[1]
});
});
}
get props() {
return Object.getOwnPropertyNames(this).map(key => ({[key]: this[key]}));
}
}
您可以使用Object.assign
(ES5 +),由弗兰克建议,或Object.defineProperty
初始化在构造函数中成员字段。后者给出选项以使属性writable
或分配getters
和/或setters
。
您可以创建一个工厂方法来获得使用你的配置类的新实例和接口的创建外部类与他们的类型的属性:
const ConfigFactory = (opts: IConfigOpts) => new Config(opts) as Config & IConfigOpts;
const cfg = ConfigFactory({
propA: 'propA',
propB: true,
propC: 5
});
let a: string = cfg.propA; // OK => defined
但是,这不会让你在类中使用this.propA
进行类型检查。你不能(但)动态绑定类型成员到一个类使用破坏。并强制您改为使用this[key]
。
如果你不想在类的外部访问特性,你可以定义叫他们的名字属性,并使用它们的类型来验证定义的类型在给定的接口这省去了使用this[key]
的方法和他们返回给定类型:
prop<TKey extends keyof IConfigOpts, TValue extends IConfigOpts[TKey]>(key: TKey): TValue {
return this[key as string];
}
这可确保使用具有keyof
查找中输入的关键存在于界面,并返回正确的类型为好。
let a: string = cfg.prop('propA'); // OK => defined
let b: boolean = cfg.prop('propB'); // OK => defined
let c: number = cfg.prop('propC'); // OK => defined
let d: number = cfg.prop('propD'); // Fail => Argument is not assignable to keyof IConfigOpts
let e: boolean = cfg.prop('propC'); // Fail => Type number is not assignle to type boolean
关于自动绑定(大量的)特性的一类唯一的好处是,你不需要编辑对象的解构在给定的构造以匹配对象的关键。例如propA
更改为propAB
。所有你必须改变的是接口声明。
为什么不只是保存的配置对象,而不是它突破到属性? – gilamran
@gilamran我的主要动机是我不希望配置选项可以在课堂以外进行修改。如果我参考配置对象,则创建者可以通过他们自己对配置对象的引用来修改配置选项,例如'let config = {myProp:'something'};新的MyClass(config); config.myProp ='somethingElse';'我不想要这个。 – Samih