目录

概念

初识泛型

泛型类型

泛型类

泛型约束

泛型工具类型

Partial

 Record

ReturnType

Pick

 Exclude

概念

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

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

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

初识泛型

定义泛型:我们把要传入函数的参数类型设为一个类型变量 T ,它能够帮助我们捕获用户传入的类型,之后出现 T 的地方,都会被替换成用户传入的类型。

  • 可以用两种方法使用。 第一种是,传入所有的参数,包含类型参数:
  • 利用了类型推论 -- 即编译器会根据传入的参数自动地帮助我们确定T的类型:

ts axios 封装泛型_ts axios 封装泛型

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

function getFirst<T>(arr: T[]): T {
    return arr[0];
}

console.log(identity<number>(10)); // 10
console.log(identity<string>('TS')); // TS
console.log(getFirst([1, 2, 3, 4])); // 1
console.log(getFirst(['a', 'b', 'c'])); // a

 其实并不是只能定义一个类型变量,我们可以引入希望定义的任何数量的类型变量。比如我们引入一个新的类型变量 U,用于扩展我们定义的 identity 函数:

function identity <T, U>(value: T, message: U) : T {
  console.log(message);
  return value;
}

console.log(identity<Number, string>(68, "Semlinker"));

 

ts axios 封装泛型_ts axios 封装泛型_02

泛型类型

<泛型变量名称>(参数1: 泛型变量, 参数2: 泛型变量, ...参数n: 泛型变量) => 泛型变量

 我们还可以使用带有调用签名的对象字面量来定义泛型函数:

let foo: { <T>(arg: T): void };
foo = function <T>(arg: T): void {
    console.log(arg);
}
foo(13); // 13

泛型接口

interface CreateArrayFunc<T> {
        (length: number, value: T): Array<T>;
    }

    let createArray: CreateArrayFunc<any>;
    createArray = function <T>(length: number, value: T): Array<T> {
        let result: T[] = [];
        for (let i = 0; i < length; i++) {
            result[i] = value;
        }
        return result;
    }

    createArray(3, 'x'); // ['x', 'x', 'x']

泛型类

泛型类看上去与泛型接口差不多。 泛型类使用( <>)括起泛型类型,跟在类名后面。

类有两部分:静态部分和实例部分。 泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。

class Animal<T> {
    name: T;
    constructor(name: T) {
        this.name = name;
    }
    action<T>(say: T) {
        console.log(say)
    }
}
let cat = new Animal('cat');
cat.action('mimi')

泛型约束

我们定义一个接口来描述约束条件。 泛型可以通过 extends 一个接口来实现泛型约束,写法如:<泛型变量 extends 接口> ,

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

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

泛型工具类型

Partial

Partial<T> 的作用就是将某个类型里的属性全部变为可选项 ?

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

student({
    name: 'zs'
})

 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" },
};

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

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 = 'a'; //不能将类型“"a"”分配给类型“T0”