TypeScript创建一个空接口对象

35

我正在使用 Angular 5 (TS) 构建一个应用程序,但在试图初始化我的接口的空对象时遇到了困难。
因此,我所见过唯一可接受的解决方案是这个:

article: Article = {} as Article;
尽管看起来合法,但它却不起作用;尝试使用article["something"]将失败,因为它只是一个空对象,没有任何

我正在寻找的结果大致如下:
export interface Article {
slug: string;
title: string;
description: string;
body: string;
tagList: string[];

初始化之后:

article = { 'slug': '', 'title': '', 'description': '', body: '', tagList: '[]' }

1
接口不是类;你需要定义一个类(例如 BlogPost ),实现 Article 接口,然后创建一个 new BlogPost() - John Ellmore
不需要是一个类。任何对象都可以实现该接口。 - JJWesterkamp
5个回答

35
一个接口并没有为实际对象定义初始值,但它定义了对象必须满足的要求,以便成为该接口的实现。
您应该创建某种类型的工厂,用于创建文章(Article)对象。这可以像这个函数一样简单:
const emptyArticle = (): Article => ({
    slug: '',
    title: '',
    description: '',
    body: '',
    tagList: [],
});

您还可以创建一个接受 Partial<Article> 对象的函数 - 如此处所述。这使您能够将初始值的子集传递给函数。此示例使用上面定义的 emptyArticle

const createArticle = <T extends Partial<Article>>(initialValues: T): Article & T => {
    return Object.assign(emptyArticle(), initialValues);
};

// Initialize a new article with a certain slug:
createArticle({ slug: 'my-awesome-article' });

15

或者更简单地通过设置默认值将Interface替换为Class,例如:

或更简化地替换InterfaceClass,可设置默认值:

export class Article {
   slug: string = '';
   title: string = '';
   description: string = '';
   body: string = '';
   tagList: string[] = [];
}

当执行let article = new Article()时,它将已经具有默认值的属性


1
谢谢,我以为有一种方法可以使用接口来实现它。 - Alex

7

接口(以及类型)只是编译时构造,用于帮助编译器验证我们的代码。因此,您使用的类型断言({} as Article)除了告诉编译器空对象文字有这种形式之外,什么也不会做。如果您想要一个“空”对象来符合您的接口,您将需要自己创建它:

interface Article {
    slug: string;
    title: string;
    description: string;
    body: string;
    tagList: string[];
}

function emptyArticle(): Article {
    return {
        slug: '',
        title: '',
        description: '',
        body: '',
        tagList: []
    }

}

好消息是编译器会警告您是否忘记为任何必填字段添加默认值。如果您想确保还指定了可选字段,则可以创建一个映射类型,从字段中删除可选项。
type Mandatory<T> = { [P in keyof T]-?: T[P] };
function emptyArticle(): Mandatory<Article> {
    return {
        ....
    }

} 

类型断言的解释很好。值得注意的是,只有在typescript 2.8(目前最新版本)中才能通过这种方式去除?修饰符。 - JJWesterkamp
@JeffreyWesterkamp 确实,在2.8之前也有进行这种操作的选项:https://dev59.com/p1UL5IYBdhLWcg3w4raQ#49655664 感谢您的点赞 :) - Titian Cernicova-Dragomir
你能否使用 TypeScript 的 Required 工具代替 Mandatory - Michael Ozeryansky
@MichaelOzeryansky 是的,你可以。这是一个非常老的答案,我不认为在当时有 Required 存在。 - Titian Cernicova-Dragomir

6

这里有另一种初始化的方式。适用于我:

const article: Article = ({} as any) as Article;

5
这违背了 TypeScript 的初衷。 - Stéphane Gerber
这实际上并没有初始化一个空的文章;它只是创建了一个带有文章类型的空对象,违背了Typescript和接口的初衷。它看起来像一篇文章,但它不会有任何字段,如果你访问任何字段,就会导致undefined错误。这个点赞数令人困惑。 - Beyondo

3
当您想要初始化一个没有属性的对象时,必须声明它可以在没有属性的情况下有效。此外,属性必须是可选的:
export interface Article {
  slug?: string;
  title?: string;
  description?: string;
  body?: string;
  tagList?: string[];
}

当你已经提到过时,你不需要初始化对象

article = { 'slug': '', 'title': '', 'description': '', body: '', tagList: '[]' }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接