网站响应时间长,个人网站推广平台大全,哈尔滨网站建设工作室,怎样制作静态网站TypeScript 接口(Interface)
本节介绍 TypeScript 各种类型接口的声明及其使用方法#xff0c;接口在 TypeScript 中是极其重要的#xff0c;我们使用接口来定义契约#xff0c;如类型命名、属性检查、函数类型定义等。
在下一节学习完类之后#xff0c;你会知道类也可以…TypeScript 接口(Interface)
本节介绍 TypeScript 各种类型接口的声明及其使用方法接口在 TypeScript 中是极其重要的我们使用接口来定义契约如类型命名、属性检查、函数类型定义等。
在下一节学习完类之后你会知道类也可以作为接口来使用。接口的种类繁多在学习过程中一定要亲手编写以达到灵活使用。 1. 解释 TypeScript 的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在 TypeScript 里接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。——官方定义 接口是对 JavaScript 本身的随意性进行约束通过定义一个接口约定了变量、类、函数等应该按照什么样的格式进行声明实现多人合作的一致性。TypeScript 编译器依赖接口用于类型检查最终编译为 JavaScript 后接口将会被移除。
// 语法格式
interface DemoInterface {}2. 应用场景
在声明一个对象、函数或者类时先定义接口确保其数据结构的一致性。
在多人协作时定义接口尤为重要。 3. 接口的好处
过去我们写 JavaScript 定义一个函数
function getClothesInfo(clothes) {console.log(clothes.price)
}let myClothes {color: black, size: XL, price: 98
}
getClothesInfo(myClothes)之前我们写 JavaScript 这样是很正常的但同时你可能会遇到下面这些问题:
getClothesInfo() // Uncaught TypeError: Cannot read property price of undefined
getClothesInfo({ color: black }) // undefined相信原因你也知道JavaScript 是 弱类型 语言并不会对传入的参数进行任何检测错误在运行时才被发现。那么通过定义 接口在编译阶段甚至开发阶段就避免掉这类错误接口将检查类型是否和某种结构做匹配。 3.1 举例说明
下面通过接口的方式重写之前的例子
实例演示
interface Clothes {color: string;size: string;price: number;
}function getClothesInfo(clothes: Clothes) {console.log(clothes.price)
}let myClothes: Clothes { color: black, size: XL, price: 98
}getClothesInfo(myClothes)代码解释 代码中定义了一个接口 Clothes在传入的变量 clothes 中它的类型为 Clothes。这样就约束了这个传入对象的 外形 与接口定义一致。只要传入的对象满足上面的类型约束那么它就是被允许的。
Tips 定义接口要 首字母大写。 只需要关注值的 外形并不像其他语言一样定义接口是为了实现。 如果没有特殊声明定义的变量比接口少了一些属性是不允许的多一些属性也是不允许的赋值的时候变量的形状必须和接口的形状保持一致。 4. 接口的属性 4.1 可选属性
接口中的属性不全是必需的。可选属性的含义是该属性在被变量定义时可以不存在。
// 语法
interface Clothes {color?: string;size: string;price: number;
}// 这里可以不定义属性 color
let myClothes: Clothes { size: XL, price: 98
}带有可选属性的接口与普通的接口定义差不多只是在可选属性名字定义的后面加一个 ? 符号。
这时仍不允许添加未定义的属性如果引用了不存在的属性时 TS 将直接捕获错误。 4.2 只读属性
一些对象属性只能在对象刚刚创建的时候修改其值。你可以在属性名前用 readonly 来指定只读属性比如价格是不能被修改的:
// 语法
interface Clothes {color?: string;size: string;readonly price: number;
}// 创建的时候给 price 赋值
let myClothes: Clothes { size: XL, price: 98
}// 不可修改
myClothes.price 100
// error TS2540: Cannot assign to price because it is a constant or a read-only propertyTypeScript 可以通过 ReadonlyArrayT 设置数组为只读那么它的所有写方法都会失效。
let arr: ReadonlyArraynumber [1,2,3,4,5];
arr[0] 6; // Index signature in type readonly number[] only permits reading代码解释 代码中的泛型语法在之后会有专门的小节介绍。
4.2.1 readonly vs const
最简单判断该用 readonly 还是 const 的方法是看要把它做为变量使用还是做为一个属性。做为 变量 使用的话用 const若做为 属性 则使用 readonly。 4.3 任意属性
有时候我们希望接口允许有任意的属性语法是用 [] 将属性包裹起来
// 语法
interface Clothes {color?: string;size: string;readonly price: number;[propName: string]: any;
}// 任意属性 activity
let myClothes: Clothes { size: XL, price: 98,activity: coupon
}代码解释 这里的接口 Clothes 可以有任意数量的属性并且只要它们不是 color size 和 price那么就无所谓它们的类型是什么。
项目案例使用 axios 库发起 HTTP 传输的时候可以写入一个自定义的属性就是因为源码中定义了一个任意属性
this.$axios({method: put,url: /cms/user,data: {nickname: this.nickname,},showBackend: true,
})5. 函数类型
除了描述带有属性的普通对象外接口也可以描述函数类型。
为了使接口表示函数类型我们需要给接口定义一个调用签名。 它就像是一个只有 参数列表 和 返回值类型 的函数定义。
interface SearchFunc {(source: string, subString: string): boolean;
}let mySearch: SearchFunc;
mySearch function(source: string, subString: string): boolean {return source.search(subString) -1;
}对于函数类型的类型检查来说函数的参数名不需要与接口里定义的名字相匹配。你可以改变函数的参数名只要保证函数参数的位置不变。函数的参数会被逐个进行检查
interface SearchFunc {(source: string, subString: string): boolean;
}let mySearch: SearchFunc;
// source src, subString sub
mySearch function(src: string, sub: string): boolean {return src.search(sub) -1;
}如果你不想指定类型TypeScript 的类型系统会推断出参数类型因为函数直接赋值给了 SearchFunc 类型变量。
interface SearchFunc {(source: string, subString: string): boolean;
}let mySearch: SearchFunc;
mySearch function(src, sub) {let result src.search(sub);return result -1;
}如果接口中的函数类型带有函数名下面两种书写方式是等价的
interface Calculate {add(x: number, y: number): numbermultiply: (x: number, y: number) number
}6. 可索引类型
可索引类型接口读起来有些拗口直接看例子
// 正常的js代码
let arr [1, 2, 3, 4, 5]
let obj {brand: imooc,type: education
}arr[0]
obj[brand]再来看定义可索引类型接口
interface ScenicInterface {[index: number]: string
}let arr: ScenicInterface [西湖, 华山, 故宫]
let favorite: string arr[0]示例中索引签名是 number类型返回值是字符串类型。
另外还有一种索引签名是 字符串类型。我们可以同时使用两种类型的索引但是数字索引的返回值必须是字符串索引返回值类型的子类型。通过下面的例子理解这句话
// 正确
interface Foo {[index: string]: number;x: number;y: number;
}// 错误
interface Bar {[index: string]: number;x: number;y: string; // Error: y 属性必须为 number 类型
}代码解释
第 12 行语法错误是因为当使用 number 来索引时JavaScript 会将它转换成 string 然后再去索引对象。也就是说用 100一个number去索引等同于使用100一个string去索引因此两者需要保持一致。 7. 类类型
我们希望类的实现必须遵循接口定义那么可以使用 implements 关键字来确保兼容性。
这种类型的接口在传统面向对象语言中最为常见比如 java 中接口就是这种类类型的接口。这种接口与抽象类比较相似但是接口只能含有抽象方法和成员属性实现类中必须实现接口中所有的抽象方法和成员属性。
interface AnimalInterface {name: string;
}class Dog implements AnimalInterface {name: string;constructor(name: string){this.name name}
}你也可以在接口中描述一个方法在类里实现它:
interface AnimalInterface {name: stringeat(m: number): string
}class Dog implements AnimalInterface {name: string;constructor(name: string){this.name name}eat(m: number) {return ${this.name}吃肉${m}分钟}
}
接口描述了类的公共部分而不是公共和私有两部分。 它不会帮你检查类是否具有某些私有成员。 8. 继承接口
和类一样接口也可以通过关键字 extents 相互继承。 这让我们能够从一个接口里复制成员到另一个接口里可以更灵活地将接口分割到可重用的模块里。
一个接口可以继承多个接口创建出多个接口的合成接口。
interface Shape {color: string;
}interface PenStroke {penWidth: number;
}interface Square extends Shape, PenStroke {sideLength: number;
}let square {} as Square;
square.color blue;
square.sideLength 10;
square.penWidth 5.0;9. 混合类型
在前面已经介绍接口可以描述函数、对象的方法或者对象的属性。
有时希望一个对象同时具有上面提到多种类型比如一个对象可以当做函数使用同时又具有属性和方法。
interface Counter {(start: number): string;interval: number;reset(): void;
}function getCounter(): Counter {let counter function (start: number) { } as Counter;counter.interval 123;counter.reset function () { };return counter;
}let c getCounter();
c(10);
c.reset();
c.interval 5.0;代码解释
第 1 行声明一个接口如果只有 (start: number): string 一个成员那么这个接口就是函数接口同时还具有其他两个成员可以用来描述对象的属性和方法这样就构成了一个混合接口。
第 7 行创建一个 getCounter() 函数它的返回值是 Counter 类型的。
let counter function (start: number) { } as Counter;第 8 行通过类型断言将函数对象转换为 Counter 类型转换后的对象不但实现了函数接口的描述使之成为一个函数还具有 interval 属性和 reset() 方法。断言成功的条件是两个数据类型只要有一方可以赋值给另一方这里函数类型数据不能赋值给接口类型的变量因为它不具有 interval 属性和 reset() 方法。
类型断言在之后的小节也会单节介绍。 10. 小结
本节介绍了接口的基本用法及其使用场景接口在 TypeScript 中至关重要TypeScript 编译器依赖接口用于类型检查。