TypeScript:泛型

73 阅读2分钟

泛型

面向对象编程的经典概念

泛型是指广泛的类型,类型也支持像函数一样的参数

type A = "hi" | 123  //TS
var a = ["hi", 123]  //JS

type F<T> = T | T[]
type FNumber = F<number>
type FString = F<string>
var fn = (x: number) => x + 1

//泛型 = 广泛的类型
type Add<T> = (a: T, b: T) => T  //这个T代表任何类型
// type AddNumber = Add<number>
// type AddString = Add<string>

const addN: Add<number> = (a, b) => a + b
const addS: Add<string> = (a, b) => a + ' ' + b

泛型的实际应用

import React, {FunctionComponent} from 'react';
type P = {
  name: string
}
const App: FunctionComponent<P> =(props)=>{
  props
  return <div>hi</div>
}

props只有两个属性,一个是name,一个是children,children是右边ReactNode的属性,name是P的属性,他们俩加起来就得到props的属性

泛型一般情况下不会只有一层,它会存在多层,泛型里面传泛型,函数能干什么,泛型就能干什么,几乎在形式上一模一样

代入法:在泛型的应用中,我们不知道属性的时候,试着用代入法,代入到最后就知道了属性。

重载

type Add<T> = (a: T, b: T) => T

const add: Add<number | string> = (a, b) => {
  return 'hi'
}
add('hi','Lily') //可以这样写
add(1, 2) //就要这样写
add('hi', 1) //存在bug
//在泛型中,如果参数同时有number或string,那么属性中无法区别哪一个是string,哪一个是number


//重载中喊多种参数
type Options = { header?: any }
function get(url: string, options?: Options): void
function get(options: Options & {url:string}): void
function get(url: string | (Options & {url:string}), options?: Options): void{
  if(arguments.length === 1){
    const myOptions = url as {url: string} & Options
    myOptions.url
  }else{
    console.log((url as string))
  }
}

//重载
function add2(a: number, b: number): number;
function add2(a: string, b: string): string;
function add2(a: any, b:any): any{
  if (typeof a === 'number' && typeof b === 'number'){
    return a + b
  }else{
    return a + ' ' + b
  }
}

add2(1, 2)  //number
add2('hi', 'lily')  //string 

export {}

在重载中,如果写add2(1, 'hi'),会出现下面的错误 :

第 1 个重载(共 2 个),“(a: number, b: number): number”,出现以下错误。
类型“string”的参数不能赋给类型“number”的参数。
第 2 个重载(共 2 个),“(a: string, b: string): string”,出现以下错误。
类型“number”的参数不能赋给类型“string”的参数。

重载是为了让函数满足多种的参数条件,一种是用typeof来判断,一种是用arguments.length(参数的长度)来判断

如何用泛型封装网络请求库

type User = {
  id: string | number;
  name: string;
  age: number;
}

type Response<T> = {
  data: T
}

type T = Omit<Partial<User>, 'id'> 
//还可以写成
//type T = Partial<Omit<User, 'id'>>
type CreateResource = (path: string)=>{
  create: (attrs: Omit<Partial<User>, 'id'>)=> Promise<Response<User>>
  delete: (id: User['id']) => Promise<Response<never>>
  update: (id: User['id'], attrs: Omit<Partial<User>, 'id'>) => Promise<Response<User>>
  get: (id: User['id']) => Promise<Response<User>>
  getPage: (page: number) => Promise<Response<User[]>>
}
const createResource = (path: string) =>{
  return {
    create(attrs){
      const url = path + 's'
      return axios.post<User>(url, {data:attrs})
    },
    delete(){},
    update(){},
    get(){},
    getPage(){}
  }
}
var userResource = createResource('/api/v1/user')

//(attrs: Omit<Partial<User>, 'id'>)是指可以穿User的所有属性,这些属性中唯独忽略掉其中的id属性

进行增删改查