1、type VS interface
官方解释:
An interface can be named in an extends or implements clause, but a type alias for an object type literal cannot.
An interface can have multiple merged declarations, but a type alias for an object type literal cannot.
翻译下的意思就是:
1、interface可以用extends继承,同时定义的接口能用于类实现,而type不行。
2、interface能用于能够声明合并,而type不行。
具体例子就是:
interface使用extends继承
interface Name {
name: string;
}
interface User extends Name {
age: number;
}
interface用于实现
interface Name {
name: string;
}
class MyName implements Name {
name: string; // Same as Name
}
interface合并
interface User {
name: string
age: number
}
interface User {
sex: string
}
/*
User 接口为 {
name: string
age: number
sex: string
}
*/
上面只是说了哪些interface能使用而type不能使用的场景,下面详细说下它们之间的异同点。
都可以描述函数和对象
- 描叙对象
interface:
interface User {
name: string
}
type:
type User = {
name: string
}
- 描叙函数
interface:
interface getName {
(id:string):string
}
type:
type getName = (id:string)=>string
都可以扩展
interface:
interface Name {
name: string
}
interface User extends Name {
age: number;
}
type:
type Name = {
name:string
}
type User = Name &{
age: number;
}
而且还能相互扩展
type Name = {
name:string
}
interface User extends Name {
age: number;
}
type能做而interface不行的
- 我们应该发现interface只能用于对象或者函数类型定义,而不能对基础类型进行定义(其实也没有任何必要),但是对定义联合类型还是很有用的
// 基本类型别名
type Name = string (意义不大)
// 联合类型
type StringOrNumber = string | number;
// 元组
type PetList = [Dog, Pet]
2、对泛型的理解
首先我们得想想typescript中为什么要用到泛型,官方的解释是:
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
简单一个例子,假如我们有一个通用的队列class,在这个队列里面我们定义一些通用对方法:
class List{
private data = [];
public push (item){
this.data.push(item)
}
}
这个List我们不知道它对data是什么类型,可能是string,也可能是number是无法确定,我们可能现传入了一个string类型,后面又传入了一个number类型,这不是ts期望的。
let aList = new List();
alist.push(1);
alist.push('2');
但是如果我们提前定义好data的类型为string,这样如果我们需要一个number类型的队列的时候就需要在一个。
class List{
private data:Array<string> = [];
public push (item:string){
this.data.push(item)
}
}
这个时候泛型就发挥作用了,它的存在就是“不预先指定具体的类型,而在使用的时候再指定类型的一种特性”
class List<T>{
private data:Array<T> = [];
public push (item:T){
this.data.push(item)
}
}
let aList = new List<string>();
alist.push('1');
alist.push('2');
alist.push(3); //error
使用场景
- 泛型函数
function backValue<T>(arg:T):T{
return arg;
}
let a = backValue<string>(1)//error
let b = backValue<string>('1')
泛型类(见上文)
泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
let fn:GenericIdentityFn<string> = (arg)=>{
return arg
}
泛型参数
我们可以随意定义自己对泛型参数(T),泛型常用 T、U、V 表示.
泛型 VS any
declare function fn<T>(arg: T): void;
declare function fn(arg: any): void;
在这里,泛型完全没有必要使用,因为它仅用于单个参数的位置