gpt4 book ai didi

javascript - 使用类和接口(interface)有什么区别?

转载 作者:数据小太阳 更新时间:2023-10-29 04:26:45 24 4
gpt4 key购买 nike

这样做有什么区别

export class Comment {
likes: string;
comment: string;

constructor(likes: string, comment: string){
this.comment = comment;
this.likes = likes;
}
}

和这个
export interface CommentInterface {
likes: string;
comment: string;
}

关于声明可观察类型
register: Observable<CommentInterface[]> {
return this.http.get()
}

最佳答案

正如 JB Nizet 非常正确地指出的那样,HTTP 请求产生的反序列化 JSON 值永远不会是类的实例。
class 的双重 Angular 色(见下文) TypeScript 中的构造使得使用 class 成为可能要描述这些响应值的形状,这是一种不好的做法,因为响应文本将被反序列化为纯 JavaScript 对象。
JavaScript 和 TypeScript 中的类声明:
在 JavaScript 中,类声明

class Comment {
constructor(likes, comment) {
this.likes = likes;
this.comment = comment;
}
}
创建一个可以使用 new 实例化的值充当本质上是工厂的东西。
在 TypeScript 中,类声明创建了两件事。
第一个是与上述完全相同的 JavaScript 类值。
第二种是描述通过编写创建的实例的结构的类型
new Comment(4, 'I love your essays')
第二个工件,类型,然后可以用作类型注释,例如在您的示例中
register(): Observable<Comment[]> {
return this.http.get()
}
上面写着 register返回 Observable Comment 的数组 class实例。
现在假设您的 HTTP 请求返回以下 JSON
[
{
"likes": 4,
"comment": "I love you oh so very much"
},
{
"likes": 1,
"comment": "I lust after that feeling of approval that only likes can bring"
}
]
但是方法声明
register(): Observable<Comment[]>;
虽然它正确地允许调用者写
register().subscribe(comments => {
for (const comment of comment) {
if (comment.likes > 0) {
likedComments.push(comment);
}
}
});
这一切都很好,不幸的是它还允许调用者编写代码
getComments() {
register().subscribe(comments => {
this.comments = comments;
});
}

getTopComment() {
// since there might not be any comments
// it is likely that a check will be made here
const [topComment] = this.comments.slice().sort((x, y) => y - x);

// BUG! Always false at runtime.
if (topComment instanceof Comment) {
return topComment;
}
}
因为评论实际上不是 Comment 的实例。类上述检查将始终失败,因此代码中存在错误。但是,TypeScript 不会捕获错误,因为我们说过 commentsComment 的实例数组类,这将使检查有效(回想一下 response.json() 返回 any 可以在没有警告的情况下转换为任何类型,因此在编译时一切看起来都很好)。
但是,如果我们将评论声明为 interface
interface Comment {
comment: string;
likes: number;
}
然后 getComments将继续输入检查,因为它实际上是正确的代码,但是 getTopComment将在 if 语句中在编译时引发错误,因为正如许多其他人所指出的那样, interface ,作为仅编译时的构造,不能像构造函数一样使用来执行 instanceof查看。编译器会告诉我们有一个错误。

备注:
除了给出的所有其他原因之外,在我看来,当你有一些表示 JavaScript/TypeScript 中普通旧数据的东西时,使用类通常是矫枉过正的。它创建了一个带有原型(prototype)的函数,并有许多我们可能不需要或关心的其他方面。
如果您使用对象,它还会丢弃您默认获得的好处。这些好处包括用于创建和复制对象的语法糖以及 TypeScript 对这些对象类型的推断。
考虑
import Comment from 'app/comment';

export default class CommentService {

async getComments(): Promse<Array<Comment>> {
const response = await fetch('api/comments', {httpMethod: 'GET'});
const comments = await response.json();
return comments as Comment[]; // just being explicit.
}

async createComment(comment: Comment): Promise<Comment> {
const response = await fetch('api/comments', {
httpMethod: 'POST',
body: JSON.stringify(comment)
});
const result = await response.json();
return result as Comment; // just being explicit.
}
}
如果 Comment是一个接口(interface),我想使用上面的服务来创建评论,我可以这样做如下
import CommentService from 'app/comment-service';

export async function createComment(likes: number, comment: string) {
const commentService = new CommentService();

await commentService.createCommnet({comment, likes});
}
如果 Comment是一门课,我需要通过需要 import 来介绍一些样板。的 Comment .当然,这也增加了耦合。
import CommentService from 'app/comment-service';
import Comment from 'app/comment';

export async function createComment(likes, comment: string) {
const commentService = new CommentService();

const comment = new Comment(likes, comment); // better get the order right

await commentService.createCommnet(comment);
}
那是两行额外的行,其中一行涉及依赖另一个模块来创建一个对象。
现在如果 Comment是一个接口(interface),但我想要一个复杂的类,在我将它提供给我的服务之前进行验证等等,我仍然可以拥有它。
import CommentService from 'app/comment-service';
import Comment from 'app/comment';

// implements is optional and typescript will verify that this class implements Comment
// by looking at the definition of the service method so I could remove it and
// also remove the import statement if I wish
class ValidatedComment implements Comment {
constructor(public likes, public comment: string) {
if (likes < 0 || !Number.isSafeInteger(likes)) {
throw RangeError('Likes must be a valid number >= 0'
}
}
}

export async function createComment(likes, comment: string) {
const commentService = new CommentService();

const comment = new ValidatedComment(likes, comment); // better get the order right

await commentService.createCommnet(comment);
}
简而言之,使用 interface 的原因有很多。描述响应的类型以及使用 TypeScript 时与 HTTP 服务交互的请求。
注:您也可以使用 type声明,它同样安全和健壮,但不那么惯用,而且 interface 周围的工具通常使它更适合这种情况。

关于javascript - 使用类和接口(interface)有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45404571/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com