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

Nic*_*ges 5 javascript constructor typescript

在此过程中,我在Todo类中添加了一个构造函数:

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

  constructor(values: Object = {}) {
    Object.assign(this, values);
  }
}
Run Code Online (Sandbox Code Playgroud)

我不明白构造函数中代码的用途。

我的应用程序似乎在有和没有它的情况下都可以工作,但我对删除代码犹豫不决

这个构造函数中 Object.assign(...) 的目的是什么?

Ali*_*deh 7

这是一种轻松地将类的参数值添加到它们各自的类字段的方法,其中类实现了该接口或至少部分植入了该接口。

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

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

  constructor(params: IPerson) {
    Object.assign(this, params);
  }
}
Run Code Online (Sandbox Code Playgroud)

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

这个 Hack 的主要问题是Object.assign 不是类型安全的。因此,以这种方式使用它与 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
      }
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用这个实用程序:

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

  constructor(params: IPerson) {
    new ClassSAssign(params, this).apply();
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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);
  }
}
Run Code Online (Sandbox Code Playgroud)