一、概念
在面对对象语言中,接口(Interface)是个很重要的概念,利用接口实现多态。在 TypeScript 中也引入了接口的概念。
后面在整顿 TypeScript 中的根本类型的时候说了对于根底类型以及数据的类型注解,还少了一个很重要的 Object
,个别就是应用接口。通过接口形容一个对象的相干属性和办法,使得 TypeScript 的类型查看能够在咱们开发的时候对其进行检测提醒。
这里要有别于其余面对对象语言的接口,TypeScript 中的类型只是用作类型检测,在最终编译成 js 后会移除接口。
TypeScript 的外围准则之一是对值所具备的 构造 进行类型查看。它有时被称做“鸭式辨型法”或“构造性子类型化”。在 TypeScript 里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
—— 官网文档介绍
这里提到一个“鸭式辨型法”,简略的说,鸭式辨型法就是判断对象是否实现接口中的所有办法,如果是那就是认为这个对象实现了接口,否则就认为没有。
点击查看鸭式辨型具体
二、简略应用
定义接口 Time
,同时定义了一些属性和办法,编译器会查看对象是否具备接口中定义的属性或办法,并且类型统一。
interface Time {
hour: number
minute: number
second: number
}
const time: Time = {
hour: 9,
minute: 0,
second: 0
}
const bad1: Time = {
hour: '9', // 不能将类型“string”调配给类型“number”。minute: 0,
second: 0
}
const bad2: Time = { // error 短少属性 "second"
hour: 9,
minute: 0
}
const bad3: Time = { // error 短少属性 "timestamp"
hour: 9,
minute: 0,
second: 0,
timestamp: '09:00:00' // error“timestamp”不在类型“Time”中
}
这里要留神一种状况,当给函数的参数进行注解的时候,只有具备接口的属性就不会报错,这个在指定参数属性的类型时很不便。
const time = {
hour: 9,
minute: 0,
second: 0,
timestamp: '09:00:00'
}
function getTime(time: { timestamp: string}): string {return time.timestamp}
getTime(time) // return '09:00:00'
三、可选属性
有时候,接口内的属性并不是所有对象都须要的,或者是针对某种状况才具备该属性,这时候就用上了可选属性:
interface User {
id: number
chineseName: string
englishName?: string
}
const user1: User = {
id: 0,
chineseName: '张三'
}
四、只读属性
如果对象的某法属性定义后是不容许批改的,能够在属性名前用 readonly
来指定它为只读。批改下下面的示例,将 id
变成只读,能够发现,在定义后不能再批改 id
的值了,这就防止了理论开发中咱们在不经意间批改了应该放弃不变的属性,缩小谬误状况。
interface User {
readonly id: number
chineseName?: string
englishName?: string
}
const user: User = {
id: 0,
chineseName: '张三'
}
user.chineseName = '李四'
user.id = 1 // error 无奈调配到 "id",因为它是只读属性,
如果只读属性并不是根底类型呢,是援用类型的状况,比方数组或者对象,就有点不一样了,只有再对只读属性进行赋值的时候会检测出谬误来:
interface User {
readonly id: number
chineseName?: string
englishName?: string
readonly friends?: User[]}
const user: User = {
id: 0,
chineseName: '张三',
users: [{
id: 1,
chineseName: '李四'
}]
}
user.friends = [] // error 无奈调配到 "friends",因为它是只读属性。user.friends = [{}] // error 无奈调配到 "friends",因为它是只读属性。user.friends[0].chineseName = '王五' // 没有检测出谬误
五、函数类型接口
TypeScript 中的接口除了形容对象类型之外,还能够形容函数的类型。和一般对象的接口一样,一样是通过 key-value 来形容函数的参数和返回,函数的参数名能够和接口定义的参数名不一样,函数的参数会一一查看,只有参数的类型与接口定义的统一就能够。
interface Func {(arg: number): string
}
const fn: Func = function(num) {return num.toFixed(2)
}
六、索引类型接口
像是 array[0]
和 obj[prop]
这些也能够通过索引类型来形容。
interface IData {// [索引签名: 索引签名的类型]: 索引返回值类型
[index: number]: string
}
const data: IData = ['8', '9', '10']
TypeScript 反对字符串和数字两种索引签名,其实也就是 对象 和数组 这两种:
interface IArr {[key: number]: string
}
interface IObj {[key: string]: string
}
const arr: IArr = ['a', 'b', 'c']
const obj: IObj = {
a: '1',
b: '2',
c: '3'
}
七、接口的继承
通过 extends
(继承)能够将一个接口的成员复制到另一个接口。
interface INum {num: number}
interface IStr {str: string}
// 能够同时继承多个
interface IComb extends INum, IStr {handle: () => void
}
const obj: IComb = {
num: 0,
str: 'some',
handle: () => { console.log('function') }
}
接口继承类
接口也能够继承类。须要留神的是接口只是继承类中的所有成员,不包含其实现,如果类具备 private 或 protected 成员,同样也会被接口继承,然而这个接口就只能被这个类或其子类实现。
class Factory {
private state
protected name
}
interface IFactory extends Factory {getName(): any
}
class factory extends Factory implements IFactory {getName() {return this.name}
}
// 类型“bad”短少类型“IFactory”中的以下属性: state, name
class bad implements IFactory {getName() {return this.name}
}
八、总结
TypeScript 的一个外围就是类型查看,应用接口进行类型查看,无效防止类型转换导致的谬误,进步了开发效率。接口自身就是面对对象语言中的一个概念,应用接口也能够更好的进行面对对象编程。