Typescript对象的构造函数中Object.assign()的用途是什么?

时间:2019-04-09 01:05:10

标签: javascript typescript constructor

一路走来,我在Todo类中添加了一个构造函数:

export class Todo {
  id: number;
  title: string;
  complete: boolean = false;
  editMode: boolean = false;

  constructor(values: Object = {}) {
    Object.assign(this, values);
  }
}

我不了解构造函数中代码的用途。

我的应用程序似乎可以使用它,也可以不使用它,但是我很犹豫删除代码

此构造方法中Object.assign(...)的用途是什么?

4 个答案:

答案 0 :(得分:2)

Object.assign没有类型检查。一种替代方法是:

const assign = <T, K extends keyof T>(...args: T[]): T =>
    args.reduce( (result, current) =>
        (Object.keys(current) as K[]).reduce((target, key) => {
            target[key] = current[key];
            return target;
        }, result)
    , args[0])
;

请注意,如果T的属性不是可选的,则传入的每个对象必须包括每个属性。如果可以保证函数返回后每个属性的存在,则可以将参数传递为Partial<T>,然后在完成后强制执行结果。

答案 1 :(得分:1)

此方法可以轻松地将类的参数值添加到它们各自的类字段中,在该类中,类将实现该接口或至少具有部分植入的接口。

interface IPerson {
  firtName: string;
  lastName: string;
}

class Person implements IPerson {
  public firtName!: string;
  public lastName!: string;

  constructor(params: IPerson) {
    Object.assign(this, params);
  }
}

您的应用程序之所以有效,是因为您似乎已经以values的回调值也足够的方式实现了这一点。

此Hack的主要问题是Object.assign is not type safe。因此,以这种方式使用它与TypeScript背道而驰。

如果要以类型安全的方式执行此操作,最好使用正确检查类型的自定义实现。像这样:

type PDM = PropertyDescriptorMap;

export class ClassSAssign<T> {
  constructor(private objectToSpread: T, private klass: T) {}

  private propertyDescriptorOptions = {
    enumerable: true,
    writable: true
  };

  public apply(): void {
    const map = this.getPropertiesDescriptorMap();
    Object.defineProperties(this.klass, map);
  }

  private getPropertiesDescriptorMap(): PDM {
    return Object.entries(this.objectToSpread).reduce(
      (obj: PDM, entry) => this.getPropertyDescriptorMap(obj, entry),
      {}
    );
  }

  private getPropertyDescriptorMap(obj: PDM, [key, value]: [string, any]): PDM {
    return {
      ...obj,
      [key]: {
        value,
        ...this.propertyDescriptorOptions
      }
    };
  }
}

,您可以像这样使用此实用程序:

class Person implements IPerson {
  public firtName!: string;
  public lastName!: string;

  constructor(params: IPerson) {
    new ClassSAssign(params, this).apply();
  }
}

如果您不想/不想使用以上内容,我建议您至少添加一些严格的类型,以保护您的类免于传递给它的值

interface IToDo {
  id?: number;
  title?: string;
}

export class Todo implements IToDo {
  public id?: number;
  public title?: string;
  public complete: boolean = false;
  public editMode: boolean = false;

  constructor(values?: IToDo) {
    Object.assign(this, values);
  }
}

答案 2 :(得分:1)

Object.assign将第二个参数的所有属性分配给第一个参数。

该代码的作用是,如果将一个对象传递给构造函数,它将把那些属性分配给所创建的对象。例如:

const todo = new Todo({ id: 1, title: 'hello' });
console.log(todo.title); // 'hello'

编辑: 因为Object.assign不是类型安全的,所以您可能应该让构造函数接受比Object更具体的内容。我建议为其创建一个接口。

答案 3 :(得分:0)

它只是将两个对象thisvalues组合在一起。根据{{​​3}}

  

Object.assign()方法用于将所有可枚举的自身属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

它用于创建对象的浅表副本,并将其属性与this的实例Todo合并。在给定的代码this中,目标对象。考虑下面的例子

let target = {a:1,b:2};
Object.assign(target,{x:"new prop 1",y:"new prop 2"});
console.log(target)