Javascript 在Typescript中深度克隆实体实例?

Javascript 在Typescript中深度克隆实体实例?,javascript,arrays,typescript,Javascript,Arrays,Typescript,尝试这样做: /** * Deep clones an array of instances of type T and returns a new array. * @param array The array to deep clone * @return A new deep clone of the array argument * * @example <pre> const original = [new Todo(), new Todo()]; con

尝试这样做:

/**
 * Deep clones an array of instances of type T and returns a new array.
 * @param array The array to deep clone
 * @return A new deep clone of the array argument
 *
 * @example
<pre>
  const original = [new Todo(), new Todo()];
  const result = [new Todo(), new Todo()];
  expect(deepClone(original)).to.eql(result);
</pre>
*/
export function deepClone<T extends Object>(array: T[]): T[] {
  return array.map((e:T) => ({...e}));
}
/**
*深度克隆T类型的实例数组并返回一个新数组。
*@param array要进行深度克隆的数组
*@返回数组参数的新深度克隆
*
*@example
const original=[new Todo(),new Todo()];
const result=[new Todo(),new Todo()];
expect(deepClone(原始)).to.eql(结果);
*/
导出函数deepClone(数组:T[]):T[]{
返回array.map((e:T)=>({…e}));
}
打字稿上写着:

[ts]排列类型只能从对象类型创建


T extends Object
是否应该处理这个问题?

如果使用扩展运算符复制对象,新对象将不是类的实例,而是没有类型的文本对象,因此它不会是现有对象的真正克隆

如果要克隆的对象是由您定义的(不是外部库),您可以执行以下操作:

constructor(obj: any) {
   Object.assign(this, obj);
}
然后在你要克隆的类中:

const clone = obj =>
  Array.isArray(obj)
    ? obj.map(item => clone(item))
    : obj instanceof Date
      ? new Date(obj.getTime())
      : (typeof obj === 'object') && obj
        ? Object.getOwnPropertyNames(obj).reduce((o, prop) => ({ ...o, [prop]: clone(obj[prop]) }), {})
        : obj;
我用这个方法


它对所有可能遇到的JavaScript对象都不起作用,但是对于来自JSON格式的服务器调用的任何东西都可能起作用。

< P>关于您的实际实现,您应该考虑使用老队友JSON来帮助您解决这个问题。

var数组:数组=[1,2,3];
var deepClone=克隆(数组);
deepClone[0]=99;
console.log({array,deepClone});//返回[1,2,3]和[99,2,3]
函数克隆(数组:T[]{
返回JSON.parse(JSON.stringify(array))作为数组;

}
这是不受支持的:不幸的是,您必须使用类型断言<代码>数组.map((e:T)=>({…e}))这很难看,但如果你知道自己在做什么,它就会起作用。仅供参考,您在约束中使用了错误的类型。它应该是
object
我试过了,但现在它说
类型“object”不能分配给类型“T”。
@AluanHaddad它越来越热了,但现在它说:
[ts]类型“object”不能转换为类型“T”。
所以在两者之间添加
数组.map((e)=>({…e}))仅当顶级属性是字符串和数字等值类型时,此选项才有效。引用对象是对象的同一个实例,而不是深度克隆。@Adrianbro您是对的,这可以通过在每个具有非原始类型的属性上定义一个setter来解决。我对解释的有效性提出质疑。这感觉像是编译器的限制,而不是答案中所述的方法的问题。唯一的问题是:结果是否满足接口T?JavaScript和TypeScript中都没有“类的实例”之类的东西。@NikolaMihajlović如评论中所述,这是TypeScript的一个限制。我的回答是,
{…e}
方法不会创建类似的对象,因为即使您不想将其称为“类的实例”,Javascript中也有类型,以及许多相关的关键字(
instanceof
typeof
new
构造函数
,等等)。并且“扩展”操作符不反映源对象的类型。
const clone = obj =>
  Array.isArray(obj)
    ? obj.map(item => clone(item))
    : obj instanceof Date
      ? new Date(obj.getTime())
      : (typeof obj === 'object') && obj
        ? Object.getOwnPropertyNames(obj).reduce((o, prop) => ({ ...o, [prop]: clone(obj[prop]) }), {})
        : obj;