泛型、接口、type理解

2020-08-12  本文已影响0人  zhangAllen

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不行的


// 基本类型别名
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;

在这里,泛型完全没有必要使用,因为它仅用于单个参数的位置

上一篇 下一篇

猜你喜欢

热点阅读