我想在打字稿小的不可变类:打字稿:联合构造类型
import * as _ from "lodash";
export class Immutable<T> {
constructor(public data:T) {
Object.freeze(data);
_.each(_.keysIn(data), (key) => {
Object.defineProperty(this, key, <PropertyDescriptor> {get:() => this.data[key]})
})
}
set(key:string, val:any):Immutable<T> {
if (_.isEqual(this.data[key], val)) {
return this;
}
let newData = {};
newData[key] = val;
return new Immutable<T>(_.defaults<T>(newData, this.data))
}
update(data:T) {
let newVal = _.defaults<T>(data, this.data);
return _.isEqual(this.data, newVal) ? this : new Immutable<T>(newVal);
}
get(key):any {
return this.data[key];
}
toJson():T {
return this.data;
}
}
现在,我必须手动添加创建一个不可变的这样const instance =<Immutable<{x: number}> & {x: number}> new Immutable({x: 1});
当T,让我可以访问X与instance.x
。我知道有一种解决方法,将new(): Immutable<T> & T
定义为某处的构造函数方法,但我只是找不到我记忆中的资源。任何人都可以指引我正确的方向?
谢谢你,罗宾
编辑
有趣的是,现在通过不可改变的工作访问的T
性质,但我真的不明白为什么(不打字稿了解Object.defineProperty在构造函数?)。
我更新了类,使子类和设置的默认值存在,如果有人有兴趣:
import * as _ from "lodash";
export class Immutable<T> {
constructor(public data:T) {
Object.freeze(data);
_.each(_.keysIn(data), (key) => {
Object.defineProperty(this, key, <PropertyDescriptor> {get:() => this.data[key]})
})
}
set(key:string, val:any):this {
if (_.isEqual(this.data[key], val)) {
return this;
}
const newData = _.defaults<T>(_.fromPairs([[key, val]]), this.data);
return this.new(newData)
}
update(data:T):this {
const newData = _.defaults<T>(data, this.data);
return _.isEqual(this.data, newData) ? this : this.new(newData);
}
new(...args:any[]):this {
return <this> (new (<any>this.constructor)(...args));
}
get(key):any {
return this.data[key];
}
toJson():T {
return this.data;
}
}
这使得某事物像这样的可能:
class Child extends Immutable<{x:number}> {
constructor(data = {x: 1}) {
super(data)
}
}
我离开的问题开放,不过,因为我还是想知道如何让打字稿知道一个导出类具有比定义更多的属性答案(或许在外部添加,或通过像我这样的构造函数)
是您的编辑说,你可以做'新的孩子({x:3})。x'? – Alex
Jep,这个测试工作在那里我完全是这样的:https://gist.github.com/rweng/ab0fa6f28b522c267ab2fe0e41c0f1a2 – rweng
该测试是为运行时行为,它没有说太多关于打字稿的类型。我假设你想要正确的打字? – Alex