TypeScript中泛型的使用详细讲解

 更新时间:2022年11月03日 09:34:48   作者:郑建007  
泛型程序设计(generic programming)是程序设计语言的一种风格或范式,下面这篇文章主要给大家介绍了关于TypeScript中泛型使用的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

一、泛型程序设计是一种编程风格或编程范式

二、案例:传入的参数类型与返回的类型一样

function identify<T>(arg: T): T {// 当前的T没有任何约束 它可以是任何类型
    return arg;
}
 
const foo = identify('foo'); // foo的类型是'foo'
const bar = identify('true'); // bar的类型是true

三、形式类型参数

 1、形式类型参数T的默认类型为boolean类型

<T = boolean>

2、必选类型参数、可选类型参数

(1)、必选类型参数:形式类型参数没有给默认类型 , 例如: <T>

(2)、可选类型参数:形式类型参数给默认类型 , 例如: <T = boolean>

(3)、形式类型参数列表中,必选类型参数不允许出现在可选类型参数之后

<T = boolean, U> // 错误
<T, U = boolean> // 正确

四、泛型约束

在形式类型参数上允许定义一个约束条件,它能够限定类型参数的实际类型的最大范围。我们将类型参数的约束条件称为泛型约束

interface point {
    x: number,
    y: string
}
 
function getPoint<T extends point>(args: T): T {
    return args
}
 
console.log(getPoint({x: 123, y: 456})); // 错误
console.log(getPoint({x: 123, y: '456'})); // 正确
console.log(getPoint({x: 123, y: '456', z: 678})); // 正确
//参数的前俩个必须有并且类型必须正确  否则错误

可以同时定义泛型约束和默认类型

<T extends number = 0 | 1>

泛型约束 ==> 类型参数

<T, U extends T>
<T extends U, U>

形式类型参数不允许直接或间接地将其自身作为约束类型

<T extends T> // 错误
<T extends U, U extends T> // 错误

类型参数T没有声明泛型约束,那么类型参数T的基约束为空对象类型字面量“{}”。除了undefined类型和null类型外,其他任何类型都可以赋值给空对象类型字面量

<T> // 类型参数T的基数约为“{}”类型

五、泛型函数

1.简介:若一个函数的函数签名(形参)中带有类型参数,那么它是一个泛型函数 

2.f1函数两个参数的类型相同,函数返回值类型是数组,数组元素类型 == 参数类型。

function f1<T>(x: T, y: T): T[] {
    return [x, y]
}
 
const a = f1(123, 456)
const b = f1('123', '456')

3.f2函数两个参数的类型不同,返回值类型为对象类型。返回值对象类型中x属性的类型与参数x类型相同,y属性的类型与参数y类型相同

function f2<T, U>(x: T,  y: U): { x: T, y: U} {
    return { x, y }
}
 
const a = f2('123', 456)
const b = f2(123, '456')

4.f3函数接受两个参数,参数a为任意类型的数组;参数f是一个函数,该函数的参数类型与参数a的类型相同,并返回任意类型。f3函数的返回值类型为参数f返回值类型的数组。

(这个代码的粘贴的   我也懵逼)

function f3<T, U>(a: T[], f: (x: T) => U): U[] {
    return a.map(f);
}
 
// f3<number, boolean> 约束T为number类型  U为boolean类型
const a: boolean[] = f3<number, boolean>([1, 2, 3], n => !! n)

六、泛型函数类型推断

function f0<T>(x: T): T {
    return x
}
 
const a = f0(123) // 推断出类型为 123
const b = f0('123') // 推断出类型为 '123'

此例中编译器推断出的不是number 和 string类型,而是字符串字面量类型123和“123”。因为TS原则,始终将字面量视为字面量类型,只在必要的时候才会将字面量类型放宽为某种基础类型,例如string类型。此例中,字符串字面量类型“123”是比string类型更加精确的类型。

类型参数只在函数签名中出现一次,则说明它与其他值没有关联,则不需要使用类型参数,直接声明实际类型即可。

几乎任何函数都可以声明为泛型函数。若泛型函数的类型参数不表示参数之间或参数与返回值之间的某种关系,那么使用泛型函数可能是一种反模式。

// 没必要使用泛型
function f<T>(x: T): void {
    console.log(x)
}
 
// 直接限定就好了
function f(x: number): void {
    console.log(x)
}

补充:应用场景

通过上面初步的了解,后述在编写 typescript 的时候,定义函数,接口或者类的时候,不预先定义好具体的类型,而在使用的时候在指定类型的一种特性的时候,这种情况下就可以使用泛型

灵活的使用泛型定义类型,是掌握typescript 必经之路

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

 /*------------基础使用方法------------*/
  function join<T, P>(first: T, second: P): T {
    return first;
  }
  //const twoParms = join<number, string>(1, '我是string');
  const twoParms = join(1, '我是string');

  /*---------泛型集合--------------*/
  function map<T>(params: Array<T>) {
    return params;
  }
  //const sanleType = map<string>(['123']);
  const sanleType = map(['123']);

  /* -----------泛型箭头函数-------------*/
  const identity = <T,>(arg: T): T => {
    return arg;
  };
  const identity2: <T>(arg: T) => T = (arg) => {
    return arg;
  };

泛型接口

 /* -------------泛型接口-------------*/
 interface ColumnProps<T> {
  key: number | string;
  title: string;
  dataIndex: keyof T; // 约束 dataIndex 值需为引用泛型 T 中的属性
}
interface ITableItem {
  key: number | string;
  name: string;
  address: string;
  age: number;
}
const columns: Array<ColumnProps<ITableItem>> = [
    {
      title: '姓名',
      dataIndex: 'name',
      key: 'name',
    },
  ];

泛型类

 /*--------------泛型类---------------*/
  class Person<T> {
    love: T;
    say: (arg: T) => T;
  }
  let myFn: IGeneric<number> = fn;
  myFn(13); //13
 
  let me = new Person<string>();
  me.love = 'TS';
  // me.love = 520; // ERROR
  me.say = function(love: string){
    return `my love is ${love}`;
  }

泛型约束

泛型可以通过 extends 一个接口来实现泛型约束,写法如:

<泛型变量 extends 接口>

<T, K extends keyof T>
//K为传入的T上已知的属性,

interface IArray {
  length: number
}
function logIndex<T extends IArray>(arg: T): void {
  for (let i = 0; i < arg.length; ++i) {
    console.log(i)
  }
}
let arr = [1, 2, 3]
// logIndex<number>(arr) // 报错
logIndex<number[]>(arr) // 允许
logIndex(arr) // 自动类型推导,允许

泛型应用场景之一

/*-------------应用场景start---------------------------*/
interface ColumnProps<T> {
  key: number | string;
  title: string;
  dataIndex: keyof T; // 约束 dataIndex 值需为引用泛型 T 中的属性
}
interface ITableItem {
  key: number | string;
  name: string;
  address: string;
  age: number;
}
interface TableProps {
  dataSource: ITableItem[];
  columns: Array<ColumnProps<ITableItem>>;
}
const MyTable = (props: TableProps) => {
  const { dataSource, columns } = props;
  return <Table dataSource={dataSource} columns={columns} />;
};
const ApplcationMod = () => {
  const dataSource = [
    {
      key: '1',
      name: '金城武',
      age: 32,
      address: '西湖区湖底公园1号',
    },
    {
      key: '2',
      name: '吴彦祖',
      age: 42,
      address: '西湖区湖底公园1号',
    },
  ];

  const columns: Array<ColumnProps<ITableItem>> = [
    {
      title: '姓名',
      dataIndex: 'name',
      key: 'name',
    },
    {
      title: '年龄',
      dataIndex: 'age',
      key: 'age',
    },
    {
      title: '住址',
      dataIndex: 'address',
      key: 'address',
    },
  ];

  return (
    <div>
      <h3>泛型应用场景</h3>
      <MyTable dataSource={dataSource} columns={columns} />
    </div>
  );
};

总结

到此这篇关于TypeScript中泛型使用的文章就介绍到这了,更多相关TypeScript泛型的使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • GreyBox技术总结(转)

    GreyBox技术总结(转)

    GreyBox是一个遮罩层的组件也称模式窗口或模态窗口(所谓模态窗口,就是指除非采取有效的关闭手段,用户的鼠标焦点或者输入光标将一直停留在其上的窗口),它运行以后可以产生不错的界面。
    2010-11-11
  • javascript常用的方法分享

    javascript常用的方法分享

    本文给大家分享了几个javascript中常用的方法,十分的实用,也很简单,有需要的小伙伴可以参考下。
    2015-07-07
  • JavaScript前端开发之实现二进制读写操作

    JavaScript前端开发之实现二进制读写操作

    这篇文章主要介绍了JavaScript前端开发之实现二进制读写操作的相关资料,需要的朋友可以参考下
    2015-11-11
  • javascript生成不重复的随机数

    javascript生成不重复的随机数

    这篇文章主要介绍了javascript在指定范围内生成不重复的随机数的方法和相关实例,有需要的小伙伴可以参考下。
    2015-07-07
  • javascript和jquery分别实现的九九乘法表代码

    javascript和jquery分别实现的九九乘法表代码

    javascript 九九乘法表 附jquery 实现的九九乘法表代码
    2010-03-03
  • 用显卡加速,轻松把笔记本打造成取暖器的办法!

    用显卡加速,轻松把笔记本打造成取暖器的办法!

    本篇文章小编为大家介绍,用显卡加速,轻松把笔记本打造成取暖器的办法!需要的朋友可以参考一下
    2013-04-04
  • JavaScript中关于base64的一些事

    JavaScript中关于base64的一些事

    base64 其实是一种编码转换方式, 将 ASCII 字符转换成普通文本, 是网络上最常见的用于传输8Bit字节代码的编码方式之一。这篇文章重点给大家介绍JavaScript中关于base64的一些事,感兴趣的朋友跟随小编一起看看吧
    2019-05-05
  • JS页面刷新与重新加载功能实现(关闭当前窗口)

    JS页面刷新与重新加载功能实现(关闭当前窗口)

    在计算机网页中如果我们想获取当前页面最新的内容,可以刷新当前页面重新获取数据,这篇文章主要给大家介绍了关于JS页面刷新与重新加载功能实现(关闭当前窗口)的相关资料,需要的朋友可以参考下
    2023-10-10
  • JavaScript实现鼠标移入随机变换颜色

    JavaScript实现鼠标移入随机变换颜色

    这篇文章主要给大家介绍了关于JavaScript实现鼠标移入随机变换颜色的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • js实现二级菜单点击显示当前内容效果

    js实现二级菜单点击显示当前内容效果

    这篇文章主要介绍了js实现二级菜单点击显示当前内容效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04

最新评论