TS中的泛型

本文详细介绍了泛型在JavaScript、接口和类中的应用,包括基本概念、如何避免冗余代码、泛型约束和常见工具类型如Partial、Record和Exclude。通过实例展示如何提升代码复用性和类型安全性。
摘要由CSDN通过智能技术生成

目录

泛型是什么?有什么作用

 泛型用法

数组泛型

一些场景的使用: 

        可以在什么地方使用泛型

        泛型默认类型

        泛型工具类型


泛型是什么?有什么作用


当我们定义一个变量不确定类型的时候有两种解决方式:

使用any
使用any定义时存在的问题:虽然 以 知道传入值的类型但是无法获取函数返回值的类型;另外也失去了ts类型保护的优势
使用泛型
泛型指的是在定义函数/接口/类型时,不预先指定具体的类型,而是在使用的时候在指定类型限制的一种特性。

 泛型用法:

在函数用法

function test <T> (arr:T):T{
  console.log(arr);
  return arr;
}
test<number>(11111);// 他返回值就是number类型的 11111
test<string | boolean>('justin')//它返回值是string类型的 justin
test<string | boolean>(true);//它返回值就是布尔类型的 true

在接口中使用泛型

interface Search {
  <T,Y>(name:A,age:B):A
}

let fn:Search = function <A, B>(name: A, id:B):A {
  console.log(name, id)
  return name;
}
fn('jusin',111);//编译器就会自动识别传入的参数,将传入的参数的类型认为是泛型指定的类型

 在类中使用泛型

class Justin<T> {
 name:A
 constructor(name: A){
  this.name = name;
 }
 action<A>(say:A) {
   console.log(say)
 }
}
let arr= new Justin('arr');
arr.action('aaa')

泛型约束

使用接口约束泛型

interface Person {
  name:string;
  age:number;
}
function student<T extends Person>(arg:T):T {
  return arg;
}

student({name:'aa'});//类型 "{ name: string; }" 中缺少属性 "age",但类型 "Person" 中需要该属性
student({ name: "aa" , age:'11'});//不能将类型“string”分配给类型“number”
student({ name: "aa" , age:11});

数组泛型

let arr:Array<number> =[1,2,3] === let arr:number[]=[1,2,3]

一些场景的使用: 

写一个函数,这个函数会返回任何传入的值。

eg:不用泛型的话,这个函数可能是下面这样:

function identity(arg: number): number {
    return arg;
}

如果我们要编写框架,就要考虑到各种返回值的情况,于是可能就会有这样的代码:

type idBoolean = (arg: boolean) => boolean;
type idNumber = (arg: number) => number;
type idString = (arg: string) => string;

很明显,我们的这些代码逻辑是相同的,但是由于需要,我们不得不写 n 遍这样的逻辑。

有些小伙伴可能会说,我们可以使用any类型来定义函数:

function identity(arg: any): any {
    return arg;
}

使用any类型会导致这个函数可以接收任何类型的arg参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。

所以为了解决算法的复用,我们引入了泛型的概念。如下所示:

function identity<T>(arg: T): T {
    return arg;
}

我们给identity添加了类型变量T。 T帮助我们捕获用户传入的类型(比如:number),之后我们就可以使用这个类型。

接下来我们就可以通过这样的语法调用 identity 函数。

identity<string>('hellojustin');

可以在什么地方使用泛型

可以在任何支持调用值的地方实现泛型。

// 作用域覆盖整个签名
1、type Filter<T> = {
    (array: T[], f: (item: T) => boolean): T[]
}

// 作用域覆盖函数调用期
2、type Filter = {
    <T>(array: T[], f: (item: T) => boolean): T[]
}

// 3 是 2 的简写形式
3、type Filter = <T>(array: T[], f: (item: T) => boolean): T[]

// 4 是 1 的简写形式
4、type Filter<T> = (array: T[], f: (item: T) => boolean): T[]

// 具名函数调用签名
5、function Filter<T>(array: T[], f: (item: T) => boolean): T[] { ...... }

泛型默认类型

泛型在定义的时候可以指定默认类型。

以 MyEvent 来举例

type MyEvent<T> = {
    target: T;
    type: string;
}

为了给事先不知道 MyEvent 将会绑定何种元素的情况提供便利,我们可以给 T 指定一个默认的类型。

type MyEvent<T = HTMLElement> = {
    target: T;
    type: string;
}

泛型工具类型


Partial


partial<T>的作用就是将某个类型中的属性全部变为可选项?
示例:

interface Person {
  name:string;
  age:number;
}
function student<T extends Person>(arg: Partial<T>):Partial<T> {
  return arg;
}


Record


Record<K extends keyof any, T>的作用是将K中所有的属性转换为T类型;示例:

interface PageInfo {
  title: string
}
type Page = 'home'|'about'|'other';
const x: Record<Page, PageInfo> = {
  home: { title: "xxx" },
  about: { title: "aaa" },
  other: { title: "ccc" },
};


Pick


Pick<T, K extends keyof T>的作用是将某个类型中的子属性挑出来,变成包含这个类型部分属性的子类型,示例:

interface Todo {
  title:string,
  desc:string,
  time:string
}
type TodoPreview = Pick<Todo, 'title'|'time'>;
const todo: TodoPreview ={
  title:'吃饭',
  time:'明天'
}

 Exclude


Exclude<T,U>的作用是将某个类型中属于另一个类型的属性移除掉,示例:

type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
const t:T0 ='b';

4.5 ReturnType
returnType<T>的作用是用于获取函数T的返回类型,示例:

type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
type T2 = ReturnType<<T>() => T>; // {}
type T3 = ReturnType<<T extends U, U extends number[]>() => T>; // number[]
type T4 = ReturnType<any>; // any
type T5 = ReturnType<never>; // any
type T6 = ReturnType<string>; // Error
type T7 = ReturnType<Function>; // Error

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值