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

新手上路,请多包涵

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

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

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

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

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

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

原文由 Nick Hodges 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 732
2 个回答

这种方法可以轻松地将类的参数值添加到类实现该接口或至少部分植入该接口的类字段中。

 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 不是类型安全 的。所以以这种方式使用它在某种程度上违背了 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);
  }
}

原文由 makeitmorehuman 发布,翻译遵循 CC BY-SA 4.0 许可协议

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> 传递,然后在完成后强制转换结果。

原文由 Michael Landis 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题