Type Hero 初级篇练习题(二)———泛型函数参数与泛型约束

85 阅读2分钟

Generic function types 泛型函数参数

为什么需要泛型函数参数

大多数情况下,我们函数参数可能是一种类型比如 string 和 number 。但有时候,编写函数时需要从输入类型参数传递到输出。

定义泛型函数参数

const createRow = <T,>(label: string, value: T, disabled = false) => ({
  //...
});

为了区别JSX语法,即使是一个泛型变量类型,后面也建议带上(逗号,)标识


// Thing 1: Start of JSX
const createRow = <T>Some JSX stuff!</T>;

// Thing 2: start of generic function
const createRow = <T>(someArg: T) => {
  /* some function stuff */
}

相关例题

定义一个函数

const mapArray = (arr, fn) => arr.map(fn);

满足下面测试用例

import { Expect, Equal } from 'type-testing';

const strings = ['1', '1', '2', '3', '5'];
const numbers = [1, 1, 2, 3, 5];

const stringsToNumbers = mapArray(strings, str => parseInt(str));
expect(stringsToNumbers).toEqual(numbers);
type test_stringsToNumber = Expect<Equal<
  typeof stringsToNumbers,
  number[]
>>;

const numbersToStrings = mapArray(numbers, num => `${num}`);
expect(numbersToStrings).toEqual(strings)
type test_numbersToStrings = Expect<Equal<
  typeof numbersToStrings,
  string[]
>>;

const numbersToNumbers = mapArray(numbers, num => num + 1);
expect(numbersToNumbers).toEqual([2, 2, 3, 4, 6])
type test_numbersToNumbers = Expect<Equal<
  typeof numbersToNumbers,
  number[]
>>;

const stringsToStrings = mapArray(strings, str => `${str}!`);
expect(stringsToStrings).toEqual(['1!', '1!', '2!', '3!', '5!'])
type test_stringsToStrings = Expect<Equal<
  typeof stringsToStrings,
  string[]
>>;

例题解析

arr很明显入参一定是数组类型, 所以可以像下面定义;

const mapArray = <Arr,>(arr:Arr[],fn)=>arr.map(fn);

可以发现fn函数参数,实际就是把第一参数arr传进来,所以只要去arr类型变量就可以了, 但是函数输出实际与输入是没有关系的,就不能在使用原来Arr泛型类型。

最后mapArray被定义如下:

const mapArray = <Arr,Result>(arr:Arr[],fn:(arg:Arr)=> Result)=>arr.map(fn);

Generic Type Constraints 泛型类型约束

定义泛型变量后,就允许我们在调用泛型的时候确定类型了,但有时候,我们需要对泛型进行约束:

这里给出一个例子,定义两个函数,一个用联合类型,一个是泛型函数参数。

image.png

  1. 对于drive,来说非泛型类型变量,它的CardType类型是固定的;

  2. 但对于T,泛型变量类型来说,由于默认没有约束 它可以传任何值,这种函数参数肯定是不符合我们期望的,所以我们必须对泛型变量做约束。

对泛型类型做约束 ,我们在泛型类型后面添加 extends CarType 就能对泛型类型做了指定约束了

image.png