0%

【050】typescript:type和interface的区别

共同点

都可以用来描述对象(Object)和函数(Function)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 类型别名
type A_Type = {
name: string,
age: number
}
type B_Type = (args: boolean) => void
const a:B_Type = (args: boolean) => args

//接口类型
interface C_Interface {
name: string,
age: number
}
interface D_Interface {
(args: boolean): void
}
const b:D_Interface = (args: boolean) => args

都可以进行继承(扩展)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
type A_Type = {
name: string,
}
type B_Type = {
age: number
}
interface C_Interface {
sex: string,
}
interface D_Interface {
phone: number | string
}

// type 继承 type
type Type_Extends_Type = A_Type & B_Type & { adrress: string }
const a: Type_Extends_Type = {
name: '翠花',
age: 18,
adrress: '中国'
}

// interface 继承 interface
interface Interface_Extends_Interface extends C_Interface, D_Interface {
job: string
}
const b: Interface_Extends_Interface = {
sex: '女',
phone: 13222222222,
job: '程序员'
}

// type 继承 interface
type Type_Extends_Interface = A_Type & C_Interface
const c: Type_Extends_Interface = {
name: '翠花',
sex: '女',
}

// interface 继承 type
interface Interface_Extends_Type extends B_Type, D_Interface {}
const d: Interface_Extends_Type = {
age: 18,
phone: 13222222222,
}

都可以实现(implements)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// interface
interface IDog {
setNameFn(name: string): void
}
class Dog implements IDog {
setNameFn(name: string): void {
console.log('取名成功')
}
}

// type
type ICat = {
setNameFn: (name: string) => void
}
class Cat implements ICat {
setNameFn(name: string): void {
console.log('取名成功')
}
}

都不会出现在编译结果里面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// ts
type AA = {
name: string
}
interface BB {
age: number
}
const cc: AA = {
name: '老王'
}
const dd: BB = {
age: 30
}

// 编译成js后
var cc = {
name: '老王'
};
var dd = {
age: 30
};

不同点

语法不同,type需要等号,interface不需要。

interface定义的是对象的结构,而非单独的类型。

1
2
3
4
5
6
type PersonType = {
name: string
}
interface PersonInterface {
name: string
}

type可以用来为任何类型(包括原始类型、函数、对象等)创建别名。

1
2
type A = string
type b = number

type可以声明联合类型。

1
2
3
4
5
type C = string | number
type D = { name: string } | { age: number }
const e: D = { name: '老王' }
const f: D = { age: 30 }
const g: D = { name: '老王', age: 30 }

type可以声明元组类型。

1
2
type H = [ string, number, boolean ]
const i: H = [ '老王', 30, true ]

interface 多次声明一个同名的接口可以合并

类型别名不能重复定义相同名字,会直接报错

1
2
3
4
5
6
7
8
9
10
interface Info_Interface {
name: string
}
interface Info_Interface {
age: number
}
const j: Info_Interface = {
name: '老王',
age: 30
}

扩展的方式不一样

接口使用 extends 关键字来进行扩展。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface K {
name: string
}
interface L {
age: number
}
interface M extends K, L {
sex: string
}
const n: M = {
name: '老王',
age: 30,
sex: '男'
}
console.log(n) // { name: '老王', age: 30, sex: '男' }

类型别名使用 & 符号进行扩展。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type O = {
name: string
}
type P = {
age: number
}
type Q = {
sex: string
} & O & P
const r: Q = {
name: '老王',
age: 30,
sex: '男'
}
console.log(r) // { name: '老王', age: 30, sex: '男' }

类型别名可以使用typeof获取实例的类型进行赋值

1
2
const div = document.createElement('div')
type S = typeof div // HTMLDivElement

类型别名可以使用in来实现类型映射

1
2
3
4
5
6
7
8
9
type Keys = 'name' | 'age'
type T = {
[ key in Keys ]: string | number
}
const u: T = {
name: '老王',
age: 30
}
console.log(u) // { name: '老王', age: 30 }

总结

官方推荐用 interface,其他无法满足需求的情况下用 type。但其实,因为 联合类型交叉类型 是很常用的,所以避免不了大量使用 type 的场景,一些复杂类型也需要通过组装后形成类型别名来使用。