假设我们有一个带有引用另一个类的属性的类。我希望能够深深克隆一个" Immutable" (或Readonly
)实例:
import * as _ from 'lodash';
interface IParent{
name: string;
}
interface IChild{
name: string;
parent: IParent;
}
public class Child implements IChild{
public name: string;
public parent: string;
constructor(props: IChild){
Object.assign(this, props);
}
toImmutable(): Readonly<IChild> {
return _.cloneDeep(this); //lodash deep clone
}
}
虽然此代码在child
实例Readonly
上创建了第一个类属性,但仍可以编辑引用的对象:
let child = new Child({
name: 'abc',
parent: { name: 123 }
});
let immutable = child.toImmutable();
immutable.name = 'abc'; //not allowed
immutable.parent.name = 'abc'; //this is allowed!!!
是否有一个优雅的解决方案可以让我只读取克隆对象的所有内容?
注意:
看起来lodash
有一个名为cloneDeepWith
的方法,它采用了#34;自定义程序&#34; ...想知道这是否可能朝着正确的方向发展。
答案 0 :(得分:1)
关键是要创建一个您要使用的自定义类型DeepReadonly<T>
,而不是Readonly<>
:
type DeepReadonly<T> = {
readonly [K in keyof T]: DeepReadonly<T[K]>;
}
此类型将递归地将readonly属性应用于所有嵌套对象。
type DeepReadonly<T> = {
readonly [K in keyof T]: DeepReadonly<T[K]>;
}
import * as _ from 'lodash';
interface IParent{
name: string;
}
interface IChild{
name: string;
parent: IParent;
}
class Child implements IChild{
public name: string;
public parent: IParent;
constructor(props: IChild){
Object.assign(this, props);
}
toImmutable(): DeepReadonly<IChild> {
return _.cloneDeep(this); //lodash deep clone
}
}
let child = new Child({
name: 'abc',
parent: { name: "123" }
});
let immutable = child.toImmutable();
immutable.name = 'abc'; //not allowed
immutable.parent.name = 'abc'; //not allowed