Javascript TypeScript—“新建”一个更好的类?

Javascript TypeScript—“新建”一个更好的类?,javascript,typescript,ecmascript-6,Javascript,Typescript,Ecmascript 6,我有很多模型,我一直都是这样构建的: interface IPerson { firstName: string; lastName: string; fullName: string; } class Person implements IPerson { public firstName: string; public lastName: string; public fullName: string; constructor(_firstName: strin

我有很多模型,我一直都是这样构建的:

interface IPerson {
  firstName: string;
  lastName: string;
  fullName: string;
}

class Person implements IPerson {
  public firstName: string;
  public lastName: string;
  public fullName: string;
  constructor(_firstName: string, _lastName: string) {
    this.firstName = _firstName;
    this.lastName = _lastName;
    this.fullName = `${this.firstName} ${this.lastName}`;
  }
}
然后我最终调用一些api来返回一些json

答复示例:

{
    "data": [
    {
      “firstName”: “John”,
      “lastName”: “Doe”
    },
    {
      “firstName”: “Jane”,
      “lastName”: “Doe”
    }
  ]
}
在得到回复后,我会通过做一些简单的事情来“重新开始”,比如:

return response.data.map d=>newpersond.firstName,d.lastName

我的问题:

我有一些模型有相当大的一组属性,将它们作为参数传入并将它们绑定到各自的属性似乎是非常冗余的,至少感觉上是这样。有没有更优雅的方法

我看到了很多与下面的例子相似的东西,但它们似乎都不是真正的“新”类中的对象,因此它的行为是正确的:连接firstName和lastName

类似的文章似乎提到了这样的事情:

var modal: IModal = {
    content: '',
    form: '',
    href: '',
    $form: null,
    $message: null,
    $modal: null,
    $submits: null
};
其他人提到了一些类似的事情:

modal: IModal = <IModal>{}

编写一个接受IPerson的构造函数


编写一个接受IPerson的构造函数

您可以使用Object.assign,以避免每次都列出属性,而是使用数据对象本身。-

更新:声明了一个筛选器函数,用于从源数据中删除不属于类的属性。但有一个缺点,类属性必须具有初始值才能在编译的javascript代码中显示。若并没有初始值,typescript类将被编译为空,并且在运行时无法获取typescript类的属性列表

function filter(obj, data) {
  return Object.getOwnPropertyNames(obj).reduce((acc, k) => {
    acc[k] = data[k];
    return acc;
  }, {})
}

class Person implements IPerson {
  public firstName: string = "";
  public lastName: string = "";
  public get fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
  constructor(data) {
    Object.assign(this, filter(this, data))
  }

}
您可以使用Object.assign,以避免每次都列出属性,而是使用数据对象本身。-

更新:声明了一个筛选器函数,用于从源数据中删除不属于类的属性。但有一个缺点,类属性必须具有初始值才能在编译的javascript代码中显示。若并没有初始值,typescript类将被编译为空,并且在运行时无法获取typescript类的属性列表

function filter(obj, data) {
  return Object.getOwnPropertyNames(obj).reduce((acc, k) => {
    acc[k] = data[k];
    return acc;
  }, {})
}

class Person implements IPerson {
  public firstName: string = "";
  public lastName: string = "";
  public get fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
  constructor(data) {
    Object.assign(this, filter(this, data))
  }

}

最简单、最少量的代码也可以实现良好的SoC IMO,就是将Json响应映射到没有功能的接口。因此,不要对这些实体使用丰富的对象/类型,将该逻辑保留在组件或html模板中。这实际上并不特定于typescript,但在反序列化时,通常使用默认构造函数。对于您的类,是否可以将连接逻辑移到fullName属性而不是构造函数中?这是可能的,但如果您可以想象,我的其他一些模型需要在类中运行一些其他函数才能完成对象。例如,如果Person API只返回生日,我需要运行一个函数来计算年龄。@mwilson-不确定为什么不能在组件、服务或模板中执行此操作?你可以按照你的建议去做,为所有返回的东西更新,但是没有神奇的LoC能帮你做到这一点。因此,您要么编写逻辑来实现这一点,然后迭代返回的对象图,要么按照我的建议执行。这是你的两个选择…@Igor:是的,这就是我目前的设置。一切都在服务中处理,但希望有一种更优雅的方式,不用所有的代码就能得到实例化的东西。我确实看到一些非常酷的IDE扩展/插件,它们允许您粘贴到JSON对象中,并为您创建类/接口。我想这很酷。。。VisualStudio也有这一点和其他一些,最简单的代码量也导致了良好的SoC IMO,就是将Json响应映射到没有功能的接口。因此,不要对这些实体使用丰富的对象/类型,将该逻辑保留在组件或html模板中。这实际上并不特定于typescript,但在反序列化时,通常使用默认构造函数。对于您的类,是否可以将连接逻辑移到fullName属性而不是构造函数中?这是可能的,但如果您可以想象,我的其他一些模型需要在类中运行一些其他函数才能完成对象。例如,如果Person API只返回生日,我需要运行一个函数来计算年龄。@mwilson-不确定为什么不能在组件、服务或模板中执行此操作?你可以按照你的建议去做,为所有返回的东西更新,但是没有神奇的LoC能帮你做到这一点。因此,您要么编写逻辑来实现这一点,然后迭代返回的对象图,要么按照我的建议执行。这是你的两个选择…@Igor:是的,这就是我目前的设置。一切都在服务中处理,但希望有一种更优雅的方式,不用所有的代码就能得到实例化的东西。我确实看到一些非常酷的IDE扩展/插件,它们允许您粘贴到JSON对象中,并为您创建类/接口。我想这很酷。。。不及物动词
sual Studio也有这个和其他一些功能,这可能会从逻辑组件中删除混乱的代码,但我认为解决不了问题,因为您仍然必须在fromIPerson中列出属性。@Hikmat G。我同意。但是,我确实喜欢传入接口并让类重新创建并返回接口的概念。这可能会从逻辑组件中删除混乱的代码,但我认为解决不了问题,因为您仍然必须在fromIPerson中列出属性。@Hikmat G。我同意。但是,我确实喜欢传入接口并让类重新创建并返回接口的概念。当有太多属性在构造函数中逐个列出它们时,我肯定会使用类似的方法。我没有执行Object.assign,而是在循环中执行for。Object.assign看起来比循环优雅1000倍。所以我认为这不是你发布这个问题的原因。我说得对吗?你甚至不想每次都手动创建新的Persondata是吗?这就是我发布这个问题的原因。我唯一不喜欢这个解决方案的地方是,如果在数据中发现了任何“额外”属性,而这些属性通常都存在,那么它们就会被扔进该模型中,即使它们不应该存在。但是,总的来说,这是迄今为止最有吸引力的解决方案。示例:const p=newperson{firstName:'frank',lastName:'smith',someOtherProperty:42};//其他属性将成为对象的一部分。这是一个不错的折衷方案。但是,这本质上意味着我需要创建一个utils文件,这样我就可以将该函数导入到我的所有类中以供使用。它只是在某种程度上与其他建议一起,采取了一些额外的步骤来处理新类。。。部分我希望有一些“开箱即用”的类型脚本功能我还没有遇到。当有太多的属性在构造函数中逐个列出它们时,我肯定会使用类似的方法。我没有执行Object.assign,而是在循环中执行for。Object.assign看起来比循环优雅1000倍。所以我认为这不是你发布这个问题的原因。我说得对吗?你甚至不想每次都手动创建新的Persondata是吗?这就是我发布这个问题的原因。我唯一不喜欢这个解决方案的地方是,如果在数据中发现了任何“额外”属性,而这些属性通常都存在,那么它们就会被扔进该模型中,即使它们不应该存在。但是,总的来说,这是迄今为止最有吸引力的解决方案。示例:const p=newperson{firstName:'frank',lastName:'smith',someOtherProperty:42};//其他属性将成为对象的一部分。这是一个不错的折衷方案。但是,这本质上意味着我需要创建一个utils文件,这样我就可以将该函数导入到我的所有类中以供使用。它只是在某种程度上与其他建议一起,采取了一些额外的步骤来处理新类。。。部分我希望有一些“开箱即用”的打字功能,我还没有遇到过。
function filter(obj, data) {
  return Object.getOwnPropertyNames(obj).reduce((acc, k) => {
    acc[k] = data[k];
    return acc;
  }, {})
}

class Person implements IPerson {
  public firstName: string = "";
  public lastName: string = "";
  public get fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
  constructor(data) {
    Object.assign(this, filter(this, data))
  }

}