前言
在面向对象语言中,接口是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类去实现。
TypeScript 中的接口是一个非常灵活的概念,除了可用于 对类的一部分行为进行抽象 以外,也常用于对「对象的形状(Shape)」进行描述。
TypeScript 的核心原则之一是对值所具有的结构进行类型检查,并且只要两个对象的结构一致,属性和方法的类型一致,则它们的类型就是一致的。 在TypeScript里,接口的作用就是为这些类型命名和为代码或第三方代码定义契约。
简单点说,在 TypeScript中,接口是一个很重要的特性,它让 TypeScript 具备了 JavaScript 所缺少的、描述较为复杂数据结构的能力。
引入主题
其实在 JavaScript 日常开发中,很多时候都需要接口来 “规范” 程序。
假设在 JavaScript 中定义一个函数,用来获取一个用户的姓名和年龄的字符串:
function getUserInfo(user) {
return `name: ${user.name}, age: ${user.age}`
}
函数调用:
getUserInfo({name: "koala", age: 18})
您可能会问,我们写 JavaScript 的时候,这个再正常不过了吧?
但请注意,如果这个 getUserInfo()
在多人开发过程中,如果它是个公共函数(多个开发者都会调用),如果不是每个人点进来看函数对应注释,可能会出现以下错误的调用:
// 1: 直接调用,不知道还需要传参数
getUserInfo() // Uncaught TypeError: Cannot read property 'name' of undefined
// 2: 只传递一个参数,不知道还有其他参数
console.log(getUserInfo({name: "王佳斌"})) // name: 王佳斌, age: undefined
// 3: 参数知道传递多少个,但不知键名
getUserInfo({name: "王佳斌", width: 560}) // name: 王佳斌, age: undefined
// ...
由于 JavaScript 是弱类型的语言,所以 并不会对我们传入的代码进行任何的检测,
😦 有些错你自己都说不清楚,但是就出了问题。
那么如何解决呢?有请 Typescript 接口登场。
创建接口
指定的接口名称,最好与普通变量名 “有所区分” ,比如接口名首字母大写、首字母前缀(In_xxx)等。
在 Typescript 中,使用 interface
关键字来定义一个接口,其中 name
就是接口名称。
interface name {}
基础使用
Typescript 接口可以规定函数的 “形状”,也可以规定变量的 “形状”,下面有两个示例。
以下 JavaScript 例子(前面已经提到了,忘记的话往前翻):
function getUserInfo(user) {
return `name: ${user.name}, age: ${user.age}`
}
这个所存在的问题大家已经知道了,下面用 Typescript 接口进行函数重构。
// 规定"形状"
interface Info {
name: string;
age: number;
}
// 函数(冒号后跟上 "接口名")
function getUserInfo({ name, age }: Info) {
return `name: ${name}, age: ${age}`
}
// 正常都传递
console.log(getUserInfo({ name: '王佳斌', age: 123 }))
// 结果OK:"name: 王佳斌, age: 123"
// 少传递一个
console.log(getUserInfo({ name: '王佳斌' }))
// Property 'age' is missing in type '{ name: string; }' but required in type 'Info'.
// 类型“{name:string;}”中缺少属性“age”,但类型“Info”中需要该属性。
// 都不传递
console.log(getUserInfo())
// Expected 1 arguments, but got 0.
// 应为1个参数,但得到了0个。
你看,这些都是在编写代码时 TypeScript 提示的错误信息,这样就避免了在使用函数的时候传入不正确的参数。
注意:在定义接口时,不要把它理解为是在定义一个对象,{}
括号包裹的是一个代码块,里面是声明语句,只不过声明的不是变量的值而是类型。声明也不用等号赋值,而是冒号指定类型。每条声明之前用换行分隔即可,也可以使用分号或者逗号。
另外,接口还可以被变量所使用(继承接口的 “形状”),如下代码所示:
// 规定"形状"
interface Info {
name: string;
age: number;
}
// 变量 "继承" 接口
const student: Info = {
name: '小王',
age: 15
}
// 测试变量
console.log(student)//{"name": "小王", "age": 15}
// 错误用法(比如写一个 "Info" 接口不存在的参数)
const err: Info = {
a: 1
}
// Object literal may only specify known properties, and 'a' does not exist in type 'Info'.
// 对象文字只能指定已知的财产,类型“Info”中不存在“a”。
可选属性
当然,TypeScript 中也允许不 “必传” 某些参数,有这个字段就做处理,没有就忽略。
如下代码所示,message
参数可以不传递。
// 使用 "?" 表示此参数非必传
interface Log {
message?: string;
}
// 函数
function print({ message }: Log) {
console.log(message || '该参数没有传递~')
}
// 传递参数
print({ message: 'hello' }) //"hello"
// 不传递
print({}) //"该参数没有传递~"
很好理解。
只读属性
TypeScript 支持将某些参数设置为 “只读”,用于限制只能在对象刚刚创建的时候修改其值,后续无法再修改。
如下代码所示,age
参数不可后期修改。
// 使用 "readonly" 关键字表示此参数"只读"
interface Info {
name: string;
readonly age: number;
}
// 创建变量("age"只能初始的时候赋值一次)
const student: Info = {
name: '小王',
age: 15
}
// 测试修改只读属性 "age"
student.age = 50
// Cannot assign to 'age' because it is a read-only property.
// 无法分配给“age”,因为它是只读属性。
此外 TypeScript 还提供了 ReadonlyArray<T>
类型,它与 Array<T>
相似,只是把所有可变方法去掉了,因此可以确保数组创建后再也不能被修改。
// 创建一个 "绝对不可修改" 的数组(number类型)
let arr: ReadonlyArray<number> = [1, 2, 3, 4]
// 测试赋值
arr[0] = 10
// Index signature in type 'readonly number[]' only permits reading.
// 类型为“只读数字[]”的索引签名只允许读取。
// 测试添加数组项
arr.push(5)
// Property 'push' does not exist on type 'readonly number[]'.
// 类型“只读数字[]”上不存在属性“push”。
// 测试赋值数组长度
arr.length = 99
// Cannot assign to 'length' because it is a read-only property.
// 无法分配给“length”,因为它是只读属性。
任意属性
有时候我们希望一个接口中除了包含必选和可选属性之外,还允许有其他的任意属性,这时我们可以使用 索引签名 的形式来满足上述要求。
如下代码所示,除了 name
必传外,后面你可以随意传递参数。文章来源:https://www.toymoban.com/news/detail-413893.html
// 使用 "[propName: string]: any" 支持任意类型
interface Person {
name: string;
[propName: string]: any;
}
// 只传递必填,其他参数不要
const a: Person = { name: '小王' }
console.log(a) //{"name": "小王"}
// 传递必填,其他参数随意传递
const b: Person = { name: '小王', age: 15, sex: '男' }
console.log(b) //{"name": "小王", "age": 15, "sex": "男"}
很好理解。文章来源地址https://www.toymoban.com/news/detail-413893.html
到了这里,关于Typescript - 通俗易懂的 interface 接口,创建接口 / 基础使用 / 可选属性 / 只读属性 / 任意属性(详细教程)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!