TypeScript中interface和type的区别
原文:https://github.com/SunshowerC/blog/issues/7
interface VS type
TypeScript中定义类型的两种方式
- 接口(interface)
- 类型别名(type alias)
interface只能定义对象类型
type声明的方式可以定义组合类型、交叉类型和原始类型
相同点
1. 都可以描述一个对象或者函数
interface
interface User {
name: string;
age: number;
}
interface SetUser {
(name: string, age: number): void;
}
type
type User = {
name: string;
age: number
}
type SetUser = (name: string, age: number): void;
2. 都允许拓展(extends)
interface和type都可以拓展,并且两者并不是互相独立的,也就是说interface可以extends type, type也可以extends interface. 虽然效果差不多,但是语法不同。
interface extends interface
interface Name {
name: string;
}
interface User extends Name {
age: number;
}
type extends type
type Name = {
name: string;
}
type User = Name & { age: number }
interface extends type
type Name = {
name: string;
}
interface User extends Name {
age: number;
}
type extends interface
interface Name {
name: string;
}
type User = Name & {
age: number;
}
不同点
1. type可以声明基本类型别名、联合类型、元祖等类型
// 基本类型别名
type Name = string;
// 联合类型
interface Dog {
wong()
}
interface Cat {
miao();
}
type Pet = Dog | Cat;
// 具体定义数组每个位置的类型
type PetList = [Dog, Pet];
2. type语句中还可以使用typeof获取实例的类型进行赋值
// 当你想要获取一个变量的类型时,使用typeof
let div = document.createElement('div');
type B = typeof div;
3. type其他骚操作
type StringOrNumber = string | number;
type Text = string | { text: string };
type NameLookup = Dictionary<string, Person>;
type Callback<T> = (data: T) => void;
type Pair<T> = [T, T];
type Coordinates = Pair<number>;
type Tree<T> = T | { left: Tree<T>, right: Tree<T> };
4. interface能够声明合并
interface User {
name: string;
age: number;
}
interface User {
sex: string;
}
User接口为:
{
name: string;
age: number;
sex: string;
}
总结
一般来说,能用interface实现,就用interface,如果不能就用type
Type Aliases的官方文档:https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-aliases
Type aliases create a new name for a type. Type aliases are sometimes similar to interfaces, but can name primitives, unions, tuples, and any other types that you’d otherwise have to write by hand.
(类型别名为类型创建一个新名称。类型别名有时类似于接口,但可以命名原语、联合、元组和其他任何类型,否则您必须手动编写这些类型)
type Second = number;
let timeInSecond: number = 10;
let time: Second = 10;
Aliasing doesn’t actually create a new type - it creates a new name to refer to that type. Aliasing a primitive is not terribly useful, though it can be used as a form of documentation.
(别名实际上并不会创建一个新类型——它只是创建一个新名称来引用该类型。尽管可以将原语用作一种文档形式,但给原语起一个别名并不是非常有用)
Just like interfaces, type aliases can also be generic - we can just add type parameters and use them on the right side of the alias declaration:
(就像接口一样,类型别名也可以是泛型的-我们可以添加类型参数并在别名声明的右侧使用它们)
type Container<T> = { value: T };
We can also have a type alias refer to itself in a property:
(我们也可以有一个类型别名引用自己的属性)
type Tree<T> = {
value: T;
left?: Tree<T>;
right?: Tree<T>
};
脑壳儿疼~~