4.TS泛型


TS泛型

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

使用场景 入参和返回值的类型有映射关系

泛型

泛型函数

// 泛型简单使用
function createArray<T>(length: number, value: T): Array<T> {
    let result: T[] = [];
    for (let i = 0; i < length; i++) {
      result[i] = value;
    }
    return result;
  }
let result = createArray2<string>(3,'x');
console.log(result);

泛型type

type Cart<T> = {list:T[]} | T[];
let c1:Cart<string> = {list:['1']};
let c2:Cart<number> = [1];

两种使用方法

// 1) 使用接口的时候确定的类型
type ICallback<T> = (item: T, idx: number) => void;
// 2) 在调用函数的时候确定了类型
type IForEach = <T>(arr: T[], callback: ICallback<T>) => void;
// type ICallback1 = <T>(item: T, idx: number) => void;
const forEach: IForEach = (arr, callback) => {
  for (let i = 0; i < arr.length; i++) {
    callback(arr[i], i); // callback 没有执行, 所以无法推导arr[i] = T
  }
};
forEach(["a", "b", "c", 1], function (item) {
  console.log(item);
});

泛型接口

约束 变量的值 为 一个泛型函数
(须变量使用时赋值T,因为 使用该变量 就相当于 使用 泛型函数)

interface Calculate{
  <T>(a:T,b:T):T
}
let add:Calculate = function<T>(a:T,b:T){
  return a;
}
add<number>(1,2);

注意上下两个例子<T>的位置,以及<T>的赋值时机

约束 变量的值 为 一个与T相关的函数
(须接口使用时赋值T)

interface Calculate<T>{
    (a:T,b:T):T
}
let add:Calculate<number> = function(a:number,b:number):number{
    return a;
}
add(1,2);

泛型类

class MyArray<T>{
    private list:T[]=[];
    add(value:T) {
        this.list.push(value);
    }
    getMax():T {
        let result=this.list[0];
        for (let i=0;i<this.list.length;i++){
            if (this.list[i]>result) {
                result=this.list[i];
            }
        }
        return result;
    }
}

使用时传入factory,约束type必须是T类型

function factory<T>(type: {new():T}): T {
  return new type(); // This expression is not constructable.
}
class Person {}
let p = factory<Person>(Person)
console.log(p)

传入多个泛型

function swap<A,B>(tuple:[A,B]):[B,A]{
  return [tuple[1],tuple[0]];
}
let swapped = swap<string,number>(['a',1]);
console.log(swapped);
console.log(swapped[0].toFixed(2));
console.log(swapped[1].length);

泛型默认值

function createArray3<T=number>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
  }
  return result;
}
let result2 = createArray3(3,'x');
console.log(result2);

泛型约束

只要含有约束的属性就行,可以有额外的属性(或者说范围比约束的还小)

interface LengthWise {
    length: number
}
//可以让泛型继承一个接口
function logger2<T extends LengthWise>(val: T) {
    console.log(val.length)
}
logger2('lzy');
logger2(1);

约束 传入的泛型 为 string 或 string[]

// 这里只能用type 不能用 interface,
// 因为interface无法表示这种类型,只能表示class或function或object
type LengthWise = string|string[]
function logger2<T extends LengthWise>(val: T) {
    console.log(val.length)
}

extends 联合类型,调用时传入变量的类型,必须小于或等于联合类型(范围更小)

普通type,调用时传入变量的类型,属性必须多于或等于type(范围更小)

function getVal<T extends object, U extends keyof T>(obj: T, key: U) {
  return obj[key];
}
getVal({ a: 1, b: 2, c: 3 }, "c");

compose

type Func<T extends any[], R> = (...a: T) => R

/**
 * Composes single-argument functions from right to left. The rightmost
 * function can take multiple arguments as it provides the signature for the
 * resulting composite function.
 *
 * @param funcs The functions to compose.
 * @returns A function obtained by composing the argument functions from right
 *   to left. For example, `compose(f, g, h)` is identical to doing
 *   `(...args) => f(g(h(...args)))`.
 */
export default function compose(): <R>(a: R) => R

export default function compose<F extends Function>(f: F): F

/* two functions */
export default function compose<A, T extends any[], R>(
  f1: (a: A) => R,
  f2: Func<T, A>
): Func<T, R>

/* three functions */
export default function compose<A, B, T extends any[], R>(
  f1: (b: B) => R,
  f2: (a: A) => B,
  f3: Func<T, A>
): Func<T, R>

/* four functions */
export default function compose<A, B, C, T extends any[], R>(
  f1: (c: C) => R,
  f2: (b: B) => C,
  f3: (a: A) => B,
  f4: Func<T, A>
): Func<T, R>

/* rest */
export default function compose<R>(
  f1: (a: any) => R,
  ...funcs: Function[]
): (...args: any[]) => R

export default function compose<R>(...funcs: Function[]): (...args: any[]) => R

export default function compose(...funcs: Function[]) {
  if (funcs.length === 0) {
    // infer the argument type so it is usable in inference down the line
    return <T>(arg: T) => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args: any) => a(b(...args)))
}

文章作者: 罗紫宇
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 罗紫宇 !
  目录