在最近的几篇文章中,深入探讨了 TypeScript 中类的使用。今天,想稍微偏离一下主题,向介绍接口的概念。如果之前使用过 C# 或 Java,可能认为接口对来说没什么新意,但实际上 TypeScript 中的接口非常酷。
接口作为数据
可能已经注意到,当讨论类时,它们可以包含行为。换句话说,它们不仅仅是关于数据,还允许添加功能来操作数据。这非常有用,但有时想要创建一个只代表数据本身的东西。想要创建一个类型安全的有用数据的表示。可能已经猜到,会说接口可以解决这个问题,是对的。
在这篇文章中,将创建一个代表电子邮件消息的东西。将能够添加收件人、主题和消息本身。将从编写一个代表单个收件人的接口开始。要创建一个接口,将把类关键字换成接口,所以收件人看起来就像这样:
interface Recipient {
email: string;
}
如果想创建一个收件人的实例,可以这样做:
const recipient: Recipient = { email: 'peter@peter.com' };
变量声明
作为一个旁注,可能已经注意到一直在用 const 关键字声明变量,但实际上并没有解释它来自哪里或它的含义。当开始谈论TypeScript时,简要地提到它是被开发成编译成 JavaScript 的。JavaScript 有三种声明变量的方式:var、let 和 const。最初,JavaScript 只有一种方式,使用 var,但这是非常有问题的。不久前,let 和 const 被引入,以更好地、不那么麻烦的形式声明变量。
让看看为什么 var 是一个问题。问题在于所谓的块作用域。块作用域指的是变量可以被看到的地方——它应该只在声明它的块中可见,所以以下代码让看到不应该看到的数据可能会让感到惊讶。
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i);
// 等等,为什么在这里可以看到 i?
在这段代码中看到的是 var 关键字没有被块作用域覆盖。这可能导致更复杂代码中不幸的副作用,因为值变得不可预测。
进入英雄:let 和 const。这些被引入是为了帮助声明尊重块作用域的变量。有两个关键字,因为 let 允许声明一个变量,然后稍后更改其值,而 const 允许声明一个变量,但它不能被更改。
回到接口
创建了一个简单的收件人接口,现在准备添加一个涵盖电子邮件本身的接口。电子邮件接口将包括 To、CC 和 BCC 收件人列表,以及主题和消息。如果在开始编写代码之前思考一下事情,生活会轻松很多,所以将确保使用电子邮件接口的人可以选择他们想要添加的收件人。由于有一个强大的收件人类型,将使用一个小的TypeScript技巧,说收件人可以接受一个收件人数组或者收件人可以是 null 使用 | null。
interface Email {
To: Recipient[] | null;
CC: Recipient[] | null;
BCC: Recipient[] | null;
Subject: string;
Message: string;
}
Recipient[] | null 的语法意味着想要一个 Recipient 项目的数组,或者想要它是 null。
现在已经定义了接口,将创建一个简单的函数,它接受一个 Email 并将其写入控制台。
function sendMessage(message: Email) {
console.log(message);
}
使用 const 关键字填充接口,就像这样(这必须在 sendMessage(email); 行之前):
const email: Email = {
To: [{
email: 'bob@bob.com'
}],
CC: [{
email: 'terry@terry.com'
}, {
email: 'chris@chris.com'
}],
BCC: null,
Subject: 'This is my email',
Message: 'This is the message inside my email'
};
注意仍然需要添加 BCC。如果没有这部分,对象的“形状”将不匹配接口,TypeScript非常擅长捕捉这样的事情。
关于向数组中添加单个项目的快速说明。在收件人条目中,每个收件人都被 { } 包围。这是向数组中添加单个条目的方式,所以添加多个条目只是一个简单的问题,就是用逗号分隔这些 { } 对。