TypeScript中的深度克隆(保留类型) [英] Deep clone in TypeScript (preserving types)

查看:256
本文介绍了TypeScript中的深度克隆(保留类型)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在TypeScript中深度克隆一个对象。这应该不是问题,因为像Lodash这样的库提供了适当的功能。但是,这些似乎丢弃了类型信息。

I need to deep clone an object in TypeScript. This shouldn't be a problem as libraries like Lodash provide appropriate functions for that. However, these seem to discard type information.

> var a = new SomeClass();
> a instanceof SomeClass;
< true
> var b = _.cloneDeep(a);
> b instanceof SomeClass;
< false

有没有办法在TypeScript中克隆对象,同时保留这些输入信息?

Is there a way to clone objects in TypeScript while preserving this typing information?

推荐答案

Typescript不会在此处丢弃类型信息。在DefinitelyTyped lodash.d.ts 文件中,您可以看到 cloneDeep 被定义为

Typescript isn't discarding type information here. In the DefinitelyTyped lodash.d.ts file, you can see that cloneDeep is defined as

cloneDeep<T>(
    val: T,
    customizer?: (value: any) => any,
    thisArg?: any
) : T

忽略我们不关心的参数,需要 T 作为输入,然后吐出输出 T 作为输出。因此,Typescript不会丢失任何类型的信息;它认为 cloneDeep 的输出与输入的类型相同。

Ignoring the arguments we don't care about, it takes a T as input, and spits out a T as output. So Typescript isn't losing any type information; it considers the output of cloneDeep to be the same type as the input.

你应该能够验证这一点通过你的编辑器:假设你有一些编辑器可以让你检查变量的类型或自动复合方法(我强烈建议,如果你不这样做)。

You should be able to verify this via your editor: assuming you have some editor that lets you inspect the type of variables or autocompletes methods (which I'd highly recommend, if you don't).

为什么 typeof 无法按预期工作?这是因为Typescript类型信息不会延续到运行时。 instanceof 是一个本机JS运算符,其中的Typescript不会改变其行为,您可以通过运行此代码段看到:

Why then is the typeof not working as you expect? It's because the Typescript type information doesn't carry over to runtime. instanceof is a native JS operator, which Typescript doesn't change the behavior of, which you can see by running this snippet:

"use strict";
class A {}

let a = new A();
let b = _.cloneDeep(a);

if (b instanceof A) {
  alert("b is an instance of A");
} else {
  alert("b is not an instance of A");
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>

b instanceof A <的原因为false是 instanceof 正在检查构造函数: x instanceof A 如果函数返回true A 是x原型链中某处的构造函数(请参阅 instanceof )。但是,Lodash在克隆对象时不使用构造函数。它不能。 (它如何知道要传递的参数?)它创建一个普通的JS对象,它包含克隆对象的所有方法,但不会重现它的原型链。

The reason that b instanceof A is false is that instanceof is checking against constructors: x instanceof A returns true if the function A is a constructor somewhere in x's prototype chain (see the MDN documentation on instanceof). Lodash, however, doesn't use constructors when it clones objects. It can't. (How would it know what arguments to pass?) It creates a plain JS object that has all the methods of the cloned object, but doesn't reproduce it's prototype chain.

在处理原始JS对象时,最好使用Lodash的克隆(以及大多数lodash的方法)。如果你将它与构造函数一起使用并且 instanceof 检查事情会变得有点模糊。

Lodash's clone (and most of lodash's methods, really) is best used when dealing with raw JS Objects. If you're using it in conjunction with constructors and instanceof checking things get a bit murky.

这里的一个解决方案是避免 instanceof 检查,以及做一些类似鸭子打字的事情;不要检查对象的构造函数是否是特定函数,但检查对象是否具有您期望的属性。

One solution here is to avoid the instanceof checking, and do something akin to duck typing; don't check that the object's constructor is a particular function, but check that the object has the properties that you expect it to.

另一种解决方案是,如注释,在你的类本身上实现一个克隆方法,它不会使用lodash。

Another solution is, as suggested in the comments, implement a clone method on your class itself, which wouldn't use lodash.

class A() {
    clone() {
        var cloned = new A(); //pass appropriate constructor args
        //make other necessary changes to make the state match
        return cloned;
    }
}

这篇关于TypeScript中的深度克隆(保留类型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆