TypeScript中泛型的使用详细讲解
作者:郑建007 发布时间:2024-04-17 10:35:23
一、泛型程序设计是一种编程风格或编程范式
二、案例:传入的参数类型与返回的类型一样
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>
);
};
来源:https://blog.csdn.net/qq_52421092/article/details/127636771
猜你喜欢
- jQuery是一个非常优秀的JavaScript 框架,使用简单灵活,同时还有许多成熟的插件可供选择,它可以帮助你在项目中加入一些非常好的效
- mysql使用left join连接出现重复问题描述在使用连接查询的时候,例如以A表为主表,左连接B表,我们期望的是A表有多少条记录,查询结
- 使用pix2pix-gan做医学图像合成的时候,如果把nii数据转成png格式会损失很多信息,以为png格式图像的灰度值有256阶,因此直接
- 需求:对于一个python list 或者numpy数组,我需要找到这个list中最大的K个数及其对应的下标。解决方式:1. 可以构造字典通
- 背景手机型号:型号:iphone 7 / iphone xs max版本:ios 10.3.1 / ios 12.1微信版本:WeChat
- 本文将通过一下几个方面来一一进行解决 1、程序的主要功能
- 动态规划是一种用来解决定义了一个状态空间的问题的算法策略。这些问题可分解为新的子问题,子问题有自己的参数。为了解决它们,我们必须搜索这个状态
- 与抓取预定义好的页面集合不同,抓取一个网站的所有内链会带来一个 挑战,即你不知道会获得什么。好在有几种基本的方法可以识别页面类型。通过URL
- 如何获取一个网站的相关信息,获取赶集网的招聘信息,本文为大家介绍利用python获取赶集网招聘信息的关键代码,供大家参考,具体内容如下imp
- ImageField的使用笔记今天完善作业写的订单系统,主要是给每一个菜品增加图片,看起来美观一些,但是没想到这个小小的需求花了我一天时间,
- 前几天,看到有人写了个superLink的东东,主要的做什么用呢?我们有时会给在大块元素加个window.location='htt
- 那么四年一度的世界杯即将要在卡塔尔开幕了,对于不少热爱足球运动的球迷来说,这可是十分难得的盛宴,而对于最后大力神杯的归属,相信很多人都满怀着
- asp+access用户登录代码,loginnew.asp网面包含了登录框及验证用户的代码an.mdb数据库名fd表名y_username用
- 现在需要一个写文件方法,将selenium的脚本运行结果写入test_result.log文件中首先创建写入方法def write_resu
- 定义和用法nodeType 属性返回被选节点的节点类型。语法:elementNode.nodeType节点编号:节点名称:1Element2
- 我们在讲模块的时候,有些人看到了内置属性,就把它们当做函数,其实还是有区别的,这里需要为大家进行明确。我们所看到的函数两边带有双下划线,这是
- 代码如下import numpy as npfrom matplotlib import pyplot as plt# 用numpy生成数据
- 简介urlparse模块主要是用于解析url中的参数 对url按照一定格式进行 拆分或拼接。urlparse库用于把url解析为
- Null模式我想每个人都有一种经历,为了获取某属性,但是有时候属性是None,那么需要你做异常处理, 而假如你想节省这样的条件过滤的代码,可
- 最近在看python脚本语言,脚本语言是一种解释性的语言,不需要编译,可以直接用,由解释器来负责解释。python语言很强大,而且写起来很简