likes
comments
collection
share

typescript怎么根据传入的参数判断函数的返回类型

作者站长头像
站长
· 阅读数 69

需求

现在我们有一个方法

function func() {
    //...
}

我们给他加一个参数

function func(param: any) {
    //...
}

然后这个方法的返回值是这个参数的类型

function func(param: any): (typeof param) {
    // ...
}

然后你会发现,这根本判断不出来,func 的返回值无论如何都是 any,因为 typeof param 在编写的时候就已经被 typescript 判断了,这意味着 typeof param 实际上已经变成了常量 any 。不会因为传入的 param 而发生改变。

泛型

很明显,我们要用泛型

function func<T>(param: any): T {
    // ...
}

这个时候假如没有返回值会报错,假设我们的返回值是自己 param

function func<T>(param: T): T {
    // ...
    return param;
}

这时候你会发现

const a = func(1); 

能够判断 a 的类型了。

但是这是最简单的情况,显然在大多数时候我们不能直接返回 param ,我们通常需要进行对 param 的类型判断,然后,再返回相应的值,并且确保返回值的类型是 T

限定范围

如果你想要限定 T 的范围,你可以使用 extends

function func<T extends string>(param: T): T

你可以规定 T 的范围到复杂类型;

function func<T extends string | number>(param: T): T

这个时候,在 func 中,你可以将 paramparam as stringparam as number 进行类型收窄。

返回参数的返回类型

有时候我们会遇到更复杂的情况,传入的 param 是一个可能返回任何值函数,这意味着它的类型对我们来说是 () => any ,而我们需要让 func 返回这个函数的返回值。

例如,有一个方法名叫 gene: () => number ,那么就要求 func(gene) 的类型是 number;

首先,我们可以参考一下上面的方案

function func<T extends () => any>(param: T): T

然后就很简单了,由于类型收窄,我们知道 T 肯定是一个函数,这个时候我们可以用到 Typescript 提供给我们的一个工具 ReturnType

function func<T extends () => any>(param: T): ReturnType<T>

试一下

function func<T extends () => any>(param: T): ReturnType<T> {
  // ...
  return param();
}

const a = func(() => 1);

可以看到 a 的类型是 number

使用场景

生成一个任意随机长度的 generator 类型返回值的数组(这里我用到了mockjs)

function mockRandomList<G extends () => any>(
  min: number,
  max: number,
  generator: G
): Array<ReturnType<G>> {
  return new Array(Random.integer(min, max))
    .fill(undefined)
    .map(() => generator()) as Array<ReturnType<G>>;
}

这里 generator 就是生成器,生成一个对象,然后通过 map 的方式生成多个对象出来。

箭头函数

还可以把它改造成箭头函数

const mockRandomList1: <G extends () => any>(
  min: number,
  max: number,
  generator: G
) => ReturnType<G>[] = (min, max, generator) => {
  return new Array(Random.integer(min, max))
    .fill(undefined)
    .map(() => generator());
};

只不过这样在函数内部就不能使用 G 了。

转载自:https://juejin.cn/post/7005870555123417124
评论
请登录