TypeScript学习——泛型

1.基本概念

泛型是一种传递类型的方式,是一种类型占位符,这种类型占位符告诉我们的(function、class或interface)我们在调用它时想要使用什么类型

const obj = {
    name: 'zhangSan',
    age: 18
}
function getValue<T,k extends keyof T>(obj: T,key: K):T[K] {
    return T[K]
}
getValue(obj,'name') // zhangSan
  • 常用的泛型变量
    • T:代表Type,在定义泛型时通常用作第一个类型变量名。
    • K:表示对象中的键类型
    • V:表示对象中的值类型
    • E:表示元素类型
2.泛型的基本使用
2.1 处理函数参数,统一输入和输出的类型
// 处理单个参数
function fn1<T>(arg:T):T {
    return arg
}

fn1(123) // 123
fn1('zhangSan') // ‘zhangSan’

// 处理多个参数
function fn2<T, U>(arg1: T,arg2: U)[T,U] {
    return [arg1, arg2]
}

fn2(123,'zhangSan') // [123,'zhangSan']

我们在使用可以有两种方式指定类型

  • 定义要使用的类型
// 这里指定了 T 的类型为 string
fn1<string>('zhangSan') // 'zhangSan'
  • TS 类型推断,自动导出类型
// 这里没有指定 T 的类型,但是 TS 可以通过实参的类型(string)推到出 T 的类型为 string
fn1('zhangSan') // 'zhangSan'

使用 type定义函数类型

type fn = <T>(arg: T) => T
const text: fn = function getObjValue(arg) {
    return arg
}  

使用 interface定义函数类型

interface Fn<T> {
    (arg: T) : T
}

2.2 泛型参数默认类型

语法:<T = default type>

// 使用 type 定义了 fn 函数,fn 函数的泛型默认是 number
type fn<T = number> = (arg: T) => T
2.3 泛型约束
  • 约束函数参数类型
// 定义一个函数打印参数的 length
function printLnegth<T>(arg:T) {
    console.log(arg.length) // 这样写会报错,因为泛型 T 并没有 length 属性
}

这时可以通过 interface 来约束泛型

interface LengthProps {
	length: number
}

function printLnegth<T extends LengthProps>(arg:T) {
    console.log(arg.length) 
}

其中<T extends LengthProps>,让泛型继承了接口 LengthProps,使得泛型T 具有了 length属性,从而使得函数参数具有了 length属性

  • 约束接口
interface KeyValue<T, U> {
    key: T,
    value: U
}

const k1: KeyValue<number, string> = {key: 123, value: 'zhangSan'}
cosnt k2: KeyValue<string,number> = {key: 'zhangSan', value: 123}
  • 约束数组
// 之前定义数组
const arr1: number[] = [1,2,3]

// 通过泛型约束数组
const arr2: Array<number> = [1,2,3]
3. 泛型工具类型
  • Partial<T>:将类型T的所有属性转换为可选属性。

interface Person {
  name: string;
  age: number;
}

const partialPerson: Partial<Person> = {
  name: 'John',
};
// partialPerson的类型为 Partial<Person>,即 { name?: string; age?: number; }
  • Required<T>:将类型T的所有属性转换为必选属性。。
interface Person {
  name?: string;
  age?: number;
}

const requiredPerson: Required<Person> = {
  name: 'John',
  age: 25,
};
// requiredPerson的类型为 Required<Person>,即 { name: string; age: number; }

  • Readonly<T>:将类型T的所有属性转换为只读属性。

interface Person {
  name: string;
  age: number;
}

const readonlyPerson: Readonly<Person> = {
  name: 'John',
  age: 25,
};
// readonlyPerson的类型为 Readonly<Person>,即 { readonly name: string; readonly age: number; }

  • Record<K, T>:创建一个类型,其中键为类型K中的每个属性,并将它们映射到类型T。
type Weekday = 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday';

const schedule: Record<Weekday, string> = {
  Monday: '9 AM - 5 PM',
  Tuesday: '9 AM - 5 PM',
  Wednesday: '9 AM - 5 PM',
  Thursday: '9 AM - 5 PM',
  Friday: '9 AM - 3 PM',
};
// schedule的类型为 Record<Weekday, string>,即 { Monday: string; Tuesday: string; Wednesday: string; Thursday: string; Friday: string; }

  • Exclude<T, U>:从类型T中排除可以赋值给类型U的所有属性。
type Numbers = 1 | 2 | 3 | 4 | 5;
type EvenNumbers = Exclude<Numbers, 1 | 3 | 5>;
// EvenNumbers的类型为 2 | 4
  • Omit<T, K>:从类型T中排除指定属性K。
interface Person {
  name: string;
  age: number;
  address: string;
}

type PersonWithoutAge = Omit<Person, 'age'>;
// PersonWithoutAge的类型为 { name: string; address: string; }
  • Pick<T, K>:从类型T中选择指定属性K。
interface Person {
  name: string;
  age: number;
  address: string;
}

type PersonNameAndAddress = Pick<Person, 'name' | 'address'>;
// PersonNameAndAddress的类型为 { name: string; address: string; }

  • NonNullable<T>:从类型T中排除null和undefined。
type Value = string | null | undefined;

const nonNullableValue: NonNullable<Value> = 'Hello';
// nonNullableValue的类型为 string
  • ReturnType<T>:获取函数类型T的返回类型。
function greet(name: string): string {
  return `Hello, ${name}!`;
}

type GreetReturnType = ReturnType<typeof greet>;
// GreetReturnType的类型为 string

  • Parameters<T>:获取函数类型T的参数类型。
function greet(name: string, age: number): string {
  return `Hello, ${name}! You are ${age} years old.`;
}

type GreetParameters = Parameters<typeof greet>;
// GreetParameters的类型为 [string, number]
4. 小结

泛型指的是在定义函数、接口或者类的时候,不预先指定具体的类型,而是在使用的时候在指定类型。泛型中的 T 就像一个占位符、或者说一个变量,在使用的时候可以把定义的类型像参数一样传入,它可以原封不动地输出。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Champion.XL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值