如何通过键入来克隆打字稿中的对象

时间:2018-08-17 12:45:42

标签: javascript typescript object types

我正在尝试从另一个对象扩展某些属性:

interface IAlice {
  foo: string;
  bar: string;
};

interface IBob extends IAlice {
  aFunction(): number;
  anotherValue: number;
};

let alice: IAlice = {
  foo: 'hi',
  bar: 'bye'
};

let bob: IBob = Object.assign({}, alice); // Typescript error no aFunction & anotherValue

bob.anotherValue = 2;
bob.aFunction = (): number => {
  return 3;
}

如您所见,打字稿返回错误。

我知道一个可行的解决方法是使bob值可选,但这并不能解决问题。或者在Object.assign内部分配值也不起作用,因为有一个函数。

无论如何,有没有让打字稿识别出将要定义的值?

2 个答案:

答案 0 :(得分:3)

如果bob的类型为IBob,则必须始终定义IBob的所有字段。最简单的解决方案是创建完全形成为IBob实例的对象:

let bob: IBob  = Object.assign({
    anotherValue: 2,
    aFunction : (): number => {
        return 3;
    }
}, alice);

如果要部分初始化对象并缺少某些字段,可以使用Partial

let bob: Partial<IBob> = Object.assign({}, alice);

bob.anotherValue = 2;
bob.aFunction = (): number => {
    return 3;
}

这将使所有字段都是可选的,这在所有情况下可能都不适用,但是最好记住Partial作为选项。

如果您真的想打字,甚至可以将IBob的字段设为可选,同时将IAlice的字段保留为必填

let bob: Partial<Pick<IBob, Exclude<keyof IBob, keyof IAlice>>> & IAlice = Object.assign({}, alice);

bob.anotherValue = 2;
bob.aFunction = (): number => {
    return 3;
}

具体说明什么是可选的而不是什么是重要的原因在于,除非您明确检查null,否则在strictNullChecks下您将无法访问可选字段。

蛮力不安全选项是仅使用类型断言来使分配工作。为了完整起见,我将其包括在内,但我会避免断言在可能的情况下是不正确的(您基本上是向编译器说谎,Object.assign的结果具有IBob的所有字段,而编译器会错过了可能由那些缺少的字段引起的错误)

let bob: IBob = Object.assign({}, alice) as IBob;
// Or (but only if you are not in a tsx file)
let bob: IBob = <IBob>Object.assign({}, alice);

答案 1 :(得分:0)

您可以这样做:

convertDotNotationToArray(objectWithDotNotation) {

    Object.entries(objectWithDotNotation).forEach(([key, val]) => {

      // Is the key of dot notation 
      if (key.includes('.')) {
        const [name, index] = key.split('.');

        // If you have not created an array version, create one 
        if (!objectWithDotNotation[name]) {
          objectWithDotNotation[name] = new Array();
        }

        // Save the value in the newly created array at the specific index 
        objectWithDotNotation[name][index] = val;
        // Delete the current dot notation key val
        delete objectWithDotNotation[key];
      }
    });

}

现在可以将let bob: IBob | IAlice = Object.assign({}, alice); IBob这两种类型的对象都分配给IAlice