首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >普通对象与模型对象的类实例

普通对象与模型对象的类实例
EN

Stack Overflow用户
提问于 2018-08-08 08:40:54
回答 2查看 2.7K关注 0票数 5

在角/TypeScript中创建模型对象的最佳实践是什么:

  1. 我是否应该在对象表示法中使用类型注释(对象是Object的普通实例)?例如let m: MyModel = { name: 'foo' }
  2. 我是否应该使用new运算符(对象是各自原型的实例)?
  3. 这两种方法是否应该混为一谈,在实际情况下使用呢?(例如,当收到来自HttpClient的响应时,普通对象,但为了方便地通过传递属性作为构造函数参数来创建实例,new MyModel('foobar') )

本问题的背景

我是TypeScript新手,和其他许多开发人员一样,我来自流行的面向对象语言,比如Java。

我理解的一个核心概念是,TypeScript中的类型注释在运行时不起作用。它们对于编译器和编辑器的自动完成都很重要。基本上,它是带有编译时类型检查的ECMAScript。

当我不知道这一点,并期望TypeScript是某种“客户端Java”时,我发现了这个角度错误报告:https://github.com/angular/angular/issues/20770

人们(不理解类型记录的类型概念)抱怨HttpClient没有将返回的普通对象转换为他们的模型类类型。其他人为这种行为辩护,并指出在JavaScript中不存在运行时类型。

这里出现了我的问题:实际上,在JavaScript中存在运行时类型。您可以使用new操作符创建原型实例,甚至可以使用instanceof操作符检查它们的构造函数。

在TypeScript中,有两种创建实例的方法:

1)使用对象表示法(如它们在角教程中所示):

代码语言:javascript
复制
hero: Hero = {
  id: 1,
  name: 'Windstorm'
};

2)使用new-operator:

代码语言:javascript
复制
hero: Hero = new Hero();

目前,我正在做一个项目,在这个项目中,这两个选项是混在一起的。例如,同一类型的模型对象在某些情况下是Object的实例,而在其他情况下是Hero的实例。

我预计这会导致稍后的问题,因为构造函数只在后一种情况下被调用。

我对于规则/最佳实践的想法是将所有模型实例定义为普通对象,并为依赖注入创建的服务、组件等使用构造函数。因此,我根本不会使用new操作符。

然而,我不确定这是否是一个好主意,我也找不到关于它的最佳实践建议。

编辑

对亲密选民重要的注意事项:我不是在这里寻找你的个人观点。我只是在寻找某种官方记载的角度最佳实践,因为我认为这是一个核心设计决策,必须从项目开始就做出,而且这些方法不应该在没有特定原因的情况下随机混合在一起。也许答案只是一个简单的“没有官方建议的决定”。

EN

回答 2

Stack Overflow用户

发布于 2018-08-08 08:58:33

在我看来,如果需要对对象本身执行复杂的操作,应该使用new运算符来创建类的新对象。

如果您只需要访问这些属性,则可以使用对象文本创建一个新对象。

这具有封装、继承等优点,来自Java背景的开发人员可以更好地与之相关。

如果您像下面这样直接分配一个对象,那么您必须显式地在其中设置函数,例如,getName函数。

代码语言:javascript
复制
hero: Hero = {
  id: 1,
  name: 'Windstorm',
  getName: function(){ // returns name }
};

但是,通过使用函数Hero定义类getName,然后创建该类的实例,无论创建实例多少次,您都会自动获得该function

为了更好地理解面向对象的Javascript,您可以遵循以下链接:

JS

关于以下问题,

“人们(不理解类型记录的类型概念)抱怨HttpClient没有将返回的普通对象转换为他们的模型类类型。”

HttpClient只是返回服务器发送的对象,它在JS上将其转换为所需的表单。您始终可以使用它的构造函数将响应映射到所需的模型实例,该构造函数可以定义如下:

代码语言:javascript
复制
constructor(hero){
  this.id = hero.id;
  this.name = hero.name;
}

您可以映射从服务器返回的数组,如下所示:

代码语言:javascript
复制
map(hero => new Hero(hero))
票数 3
EN

Stack Overflow用户

发布于 2018-08-08 09:38:09

实际上,JavaScript中有运行时类型。

有点。值可以有某种类型,但是变量和属性没有绑定到它们的类型。也就是说,如果您键入网络请求等。

代码语言:javascript
复制
  fetch("someurl").then(res => res.json()) as Promise<IUser>

网络请求突然返回用户以外的其他内容,没有什么会失败,因为在运行时类型记录类型不存在。但是,这种行为可以很容易地添加到打字机上:

代码语言:javascript
复制
  function isUser(user: any) : user is IUser {
     return Number.isInteger(user.id) && typeof user.name === "string";
  }

它允许您在运行时执行类型检查:

代码语言:javascript
复制
 const result = await fetch("someurl");
 if(!isUser(result)) throw new Error();
 // result is definetly a IUser here

我应该使用继承还是不继承?

这是一个偏好问题。我曾经编写过一个大量使用数据库的应用程序,所以我不得不进行大量的序列化/反序列化,而且总是将来自db的响应打包到一个类实例中,这让我非常恼火。因此,对于我的db模型,我开始使用以下模式:

代码语言:javascript
复制
  type User = {
   name: string;
   id: number;
 };

 const User = {
   get(id: number): User { /*...*/ }
   changeName(user: User, name: string) { /*..*/ }
};

这让我可以写:

代码语言:javascript
复制
 const admin: User = User.get(123);

我可以简单地在db上做类型转换,而且我都有类型安全性和很好的API。

对于您的usecase来说,这是否是一个好的模式实际上取决于您做了多少序列化/反序列化。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51742249

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档