接口算是官方文档里的第一个知识点了, 这篇文章会简单介绍 TypeScrip 里的接口.
类型
在说接口之前我们先来了解下 TypeScript 里的类型, 因为在接口的使用和类型密不可分.
JS 类型
JS 有 7 种数据类型
- number
- string
- boolean
object, 里面包含 Array, Function, Date, Object, RegExp 等
symbol, 这是 ES 6 里的, 主要用来表示一个东西是唯一的, 实际上比较少用. 好吧, 根本没用过...
null, 表示空
undefined, 表示未定义
- let bool: boolean = true
- let str: string = 'Hi'
- let num: number = 1.222
- let obj: object = {
- name: 'Jack'
- }
- let n: null = null
- let u: undefined = undefined
TS 的新类型
any
如果在 TS 里没有声明类型, 那么默认就是 any 类型, 这样就直接一夜回到 JS 时代.
- let a: number = 1
- a = 'Hello' // 报错
- let a: any = 1
- a = 'Hello' // OK
- enum
枚举类主要用来规定只能选 XXX 或者 YYY, 如
- enum Gender {
- Male = 'Male',
- Female = 'Female'
- }
- let gender: Gender = Gender.Male
- gender = Gender.Female
- console.log(gender) // 'Female'
- gender = Gender.Woman // 报错
而如果不在 enum 里初始化, 那么 Male 和 Female 的值就会以数值的方式显示.
- enum Gender {
- Male,
- Female
- }
- let gender: Gender = Gender.Male
- gender = Gender.Male
- console.log(gender) // 0
- gender = Gender.Female
- console.log(gender) // 1
- void
这个类型就是指空值, 在 C 语言和 Java 里应该是很常见的, 一般用在函数的返回值里.
- function fn(): void {
- console.log('fn')
- }
断言
断言的用法是主观地认为这个变量的类型是什么, 如
- let n: any = '123'
- console.log(<string>n.split(''))
这里主观地认为 n 是一个字符串, 但是声明的时候确是 any 类型. 如果主观认为错了, 会报错.
- let n: any = 123
- console.log(<string>n.split('')) // 报错
也可以用 as 来断言.
- let n: any = '123'
- console.log((n as string).split(''))
这个一般可以用在表单组件的测试用例里, 首先模拟用户输入非法类型, 然后 expect(xxxx).to. 抛出 TS 主观错误 就可以完成一个测试用例了.
接口基础
现在回到我们的主题. 在学习 Java 的时候我就觉得这个名字很难理解, 不知道用来干嘛的, 因为 Java 还有一个抽象类, 两者很像而且使用场景差不多, 但是用法又有点差别, 真的烦. 幸好 TS 里就只有接口, 还是容易理解一些.
接口简单来说就是规定一些 "事", 在后台中, 接口指的是双方规定的 API, 在 TS 里接口一般指这个变量拥有什么东西.
- interface Shape {
- head: string;
- ARM: string;
- }
- interface Human {
- name: string;
- age: number;
- shape: Shape;
- say(Word: string): void;
- }
- let jack: Human = {
- name: 'Jack',
- age: 18,
- shape: {
- head: 'head',
- ARM: 'arm'
- },
- say(Word: string) {
- console.log(Word)
- }
- }
- jack.say('hi')
上面规定了类型为 Shape 的变量应该有 head 和 ARM, 而 Human 类型的应该有 name, age, shape, say 属性. 其中还对函数以及 shape 做了一些规定.
这就是接口, 不过是一些规范而已.
接口里的属性
接口除了对属性类型做了规定, 还能做以下规定
- readonly
- interface Human {
- readonly name: string
- }
- let jack: Human = {
- name: 'Jack'
- }
- jack.name = 'Ivan' // 报错: name 是只读的
这里指定 name 是只读的, 初始化后就不能再次赋值了.
可选
有时候我们不一定要设置对象里的某个属性, 接口里可以用 "?" 来表示一个属性是否是可选的.
- interface Human {
- gender: string,
- age?: number
- }
- let jack: Human = {
- gender: 'Male'
- // 可以不赋值 age 属性, 因为是可选的
- }
描述属性
除此之外, 我们还可以控制接口里属性规定的写法, 不懂? 看代码.
- interface Rect {
- height: number;
- width: number;
- [propName: string]: number
- }
这里规定 Rect 这个接口里 Key: Value 对只能是 Key 为 string 类型, 而 Value 为 number 类型.
函数接口
因为函数也是对象, 所以我们也可以通过接口来对函数做 "规定".
- interface Fn {
- (a: number, b: number): number;
- }
- let add: Fn = function(a: number, b: number): number {
- return a + b
- }
- console.log(add(1, 2))
这里定义了 Fn 接口, 规定了参数的类型为 number, 返回值的类型为 number.
接口的继承
就像 ES 6 的 class 一样, 接口也可以做继承操作, 效果就是会继承父接口的 "规定".
- interface Animal {
- move(): void;
- }
- interface Human extends Animal {
- name: string;
- age: number;
- }
- let jack: Human = {
- age: 18,
- name: 'Jack',
- move() {
- console.log('move')
- }
- }
Human 接口继承了 Animal 里的 move 函数的 "规定", 所以在初始化 jack 变量时也要加上 move 函数, 否则报错.
来源: http://www.jianshu.com/p/6d6b6972182f