我们从一个入门教程开始了本系列,向您介绍了不同的TypeScript功能。 它还教您如何安装TypeScript,并建议了一些IDE,可用来编写和编译自己的TypeScript代码。
在第二篇教程中,我们介绍了TypeScript中可用的不同数据类型,以及如何使用它们可以帮助您避免很多错误。 将数据类型(如string
分配给特定变量将告诉TypeScript您只想为其分配字符串。 依靠此信息,TypeScript可以在以后尝试执行不应该在字符串上执行的操作时向您指出。
在本教程中,您将学习TypeScript中的接口 。 使用接口,您可以更进一步,并在代码中定义更复杂的对象的结构或类型。 就像简单的变量类型一样,这些对象还必须遵循您创建的一组规则。 这可以帮助您更自信地编写代码,减少出错的机会。
创建我们的第一个界面
假设您的代码中有一个湖泊对象,并使用它来存储有关世界各地最大的湖泊的信息。 该湖泊对象将具有诸如湖泊的名称,面积,长度,深度以及该湖泊所处国家的属性。
湖泊的名称将存储为字符串。 这些湖泊的长度将以公里为单位,面积将以平方公里为单位,但是这两个属性都将存储为数字。 湖泊的深度将以米为单位,也可能是浮标。
由于所有这些湖泊都非常大,因此它们的海岸线通常不仅限于一个国家。 我们将使用一个字符串数组来存储特定湖岸线上所有国家的名称。 布尔值可用于指定湖泊是咸水还是淡水。 以下代码段为我们的Lake对象创建了一个接口。
interface Lakes {
name: string,
area: number,
length: number,
depth: number,
isFreshwater: boolean,
countries: string[]
}
Lakes
界面包含创建湖对象时要使用的每个属性的类型。 如果现在尝试为这些属性中的任何一个分配不同类型的值,则会出现错误。 这是一个存储有关我们的第一个湖的信息的示例。
let firstLake: Lakes = {
name: 'Caspian Sea',
length: 1199,
depth: 1025,
area: 371000,
isFreshwater: false,
countries: ['Kazakhstan', 'Russia', 'Turkmenistan', 'Azerbaijan', 'Iran']
}
如您所见,为这些属性分配值的顺序无关紧要。 但是,您不能忽略一个值。 您将必须为每个属性分配一个值,以避免在编译代码时出错。
这样,TypeScript可以确保您不会错误地遗漏任何必需的值。 这是一个示例,其中我们忘记为湖泊分配depth
属性的值。
let secondLake: Lakes = {
name: 'Superior',
length: 616,
area: 82100,
isFreshwater: true,
countries: ['Canada', 'United States']
}
下面的屏幕截图显示了我们忘记指定depth
之后在Visual Studio Code中显示的错误消息。 如您所见,该错误明确指出我们缺少湖泊对象的depth
属性。
![TypeScript界面中缺少属性值](https://i-blog.csdnimg.cn/blog_migrate/02d969fd66f3cdb069ac9a3eb077a445.png)
使接口属性为可选
有时,您可能只需要某些特定对象的属性。 例如,假设您要添加一个属性以指定湖被冻结的月份。 如果像现在一样将属性直接添加到接口,则对于其他未冻结且因此没有frozen
属性的湖泊,您将收到错误消息。 同样,如果将该属性添加到已冻结但未在接口声明中添加的湖泊中,仍然会收到错误消息。
在这种情况下,可以在属性名称后添加问号( ?
),以在接口声明中将其设置为可选。 这样,您不会因缺少属性或未知属性而收到错误消息。 下面的例子应该清楚。
interface Lakes {
name: string,
area: number,
length: number,
depth: number,
isFreshwater: boolean,
countries: string[],
frozen?: string[]
}
let secondLake: Lakes = {
name: 'Superior',
depth: 406.3,
length: 616,
area: 82100,
isFreshwater: true,
countries: ['Canada', 'United States']
}
let thirdLake: Lakes = {
name: 'Baikal',
depth: 1637,
length: 636,
area: 31500,
isFreshwater: true,
countries: ['Russia'],
frozen: ['January', 'February', 'March', 'April', 'May']
}
使用索引签名
当相当多的对象要使用可选属性时,它们是有用的。 但是,如果每个湖也都有自己独特的属性集,例如经济活动,该湖或该湖周围定居点繁荣的各种动植物种群呢? 在接口本身的声明内添加这么多不同的属性并使它们成为可选属性并不理想。
作为解决方案,TypeScript允许您借助索引签名将额外的属性添加到特定对象。 在接口声明中添加索引签名,可以为创建的不同对象指定任意数量的属性。 您需要对界面进行以下更改。
在此示例中,我使用了索引签名来添加有关湖泊周围不同居民点的信息。 由于每个湖泊都有自己的住区,因此使用可选属性并不是一个好主意。
interface Lakes {
name: string,
area: number,
length: number,
depth: number,
isFreshwater: boolean,
countries: string[],
frozen?: string[],
[extraProp: string]: any
}
let fourthLake: Lakes = {
name: 'Tanganyika',
depth: 1470,
length: 676,
area: 32600,
isFreshwater: true,
countries: ['Burundi', 'Tanzania', 'Zambia', 'Congo'],
kigoma:'Tanzania',
kalemie: 'Congo',
bujumbura: 'Burundi'
}
再举一个例子,假设您正在创建具有不同类型敌人的游戏。 所有这些敌人将具有一些共同的属性,例如大小和健康状况。 这些属性可以直接包含在接口声明中。 如果这些敌人的每种类别都有一套独特的武器,则可以在索引签名的帮助下包括这些武器。
只读属性
当使用不同的对象时,可能需要使用仅在首次创建对象时才应修改的属性。 您可以在接口声明中将这些属性标记为readonly
。 这类似于使用const
关键字,但是const
应该与变量一起使用,而readonly
是针对属性的。
TypeScript还允许您使用ReadonlyArray<T>
将数组设置为ReadonlyArray<T>
。 创建一个只读数组将导致从其中删除所有变异方法。 这样做是为了确保以后不能更改单个元素的值。 这是在接口声明中使用只读属性和数组的示例。
interface Enemy {
readonly size: number,
health: number,
range: number,
readonly damage: number
}
let tank: Enemy = {
size: 50,
health: 100,
range: 60,
damage: 12
}
// This is Okay
tank.health = 95;
// Error because 'damage' is read-only.
tank.damage = 10;
功能和接口
您还可以使用接口来描述函数类型。 这要求您给函数一个带有其参数列表和返回类型的调用签名。 您还需要为每个参数提供名称和类型。 这是一个例子:
interface EnemyHit {
(name: Enemy, damageDone: number): number;
}
let tankHit: EnemyHit = function(tankName: Enemy, damageDone: number) {
tankName.health -= damageDone;
return tankName.health;
}
在上面的代码中,我们声明了一个函数接口,并使用它定义了一个函数,该函数从其运行状况中减去对坦克造成的伤害。 如您所见,接口声明中的参数和代码的定义不必使用相同的名称。
最后的想法
本教程向您介绍了接口以及如何使用它们来确保编写更健壮的代码。 现在,您应该能够使用可选和只读属性创建自己的接口。
您还学习了如何使用索引签名将各种其他属性添加到接口声明中未包括的对象。 本教程旨在使您开始使用TypeScript中的接口,并且可以在官方文档中阅读有关此主题的更多信息 。
在下一个教程中,您将学习TypeScript中的类。 如果您对接口有任何疑问,请在评论中告诉我。
翻译自: https://code.tutsplus.com/tutorials/typescript-for-beginners-part-3-interfaces--cms-29439