关于对TypeScript泛型参数的默认值理解


Posted in Javascript onJuly 15, 2022

泛型简介

软件工程中,我们不仅要创建一致的定义良好的 API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。

在像C# 和 Java 这样的语言中,可以使用 泛型 来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。

举个?

举个最简单的例子来理解泛型?

function getVal(val: string): string {
  return val
}

上述代码很简单,约束 getVal 这个函数入参为 string 类型,约束它的返回值和它的入参一样,也是 string 类型。

关于对TypeScript泛型参数的默认值理解

如上所示,我们传入数值 1 会报错。传入正确类型的参数后,通过上述图像,可以看出 result2 可以调用字符串相关的属性和方法,这是因为 IDE 已经预先推断出了 result2 的类型。

上面的例子是 TypeScript 最基本的应用。此时,我们不妨做一个思考??,getVal 函数就只能接收 string 入参吗?我如果想要实现传入任意类型的值,函数的返回值就是该任意类型怎么实现?

举个??

完成上述提出的疑问可以使用泛型,代码如下?

function getVal<T>(val: T): T {
  return val
}

添加一点测试代码:

关于对TypeScript泛型参数的默认值理解

这一次我们可以传入任何类型的值都不会报错,并且都能够享受 IDE 预推断带来智能提示,这就是 TypeScript 的核心魅力——类型推断和类型约束。

我对于泛型的理解就是:

关于对TypeScript泛型参数的默认值理解

我们程序员在看到 '123'true 等变量时,我们一眼就能看出它是什么类型,计算机当然也能够识别出来。TypeScript 引擎通过解析 AST 的方式推断出了 getVal 的入参类型为 string ,将推断出来的类型用一个变量 T 存起来,这样我们可以将 T 灵活的运用在各种地方。总之,我们可以将泛型看成是一个变量或者是一个形参,只不过在 JavaScript 中变量存储的是,而 TypeScript 中存储的是类型罢了。

泛型参数的默认值——函数重载

我们在上面说到,泛型可以看成是一个形参。在 JavaScript 中形参可以设置一个默认值,那么在 TypeScript 中的泛型参数同样可以设置一个默认值。我们来看一下官方的示例代码?

declare function create(): Container<HTMLDivElement, HTMLDivElement[]>;
declare function create<T extends HTMLElement>(element: T): Container<T, T[]>;
declare function create<T extends HTMLElement, U extends HTMLElement>(
  element: T,
  children: U[]
): Container<T, U[]>;

示例代码中缺少 Container 类型声明,并且函数只有类型声明没有的具体执行代码块,直接复制到编辑器中会报错。这里我们尝试补充一下,如下:

type Container<T, U> = {element: T, children: U}

function create(): Container<HTMLDivElement, HTMLDivElement[]>;
function create<T extends HTMLElement>(element: T): Container<T, T[]>;
function create<T extends HTMLElement, U extends HTMLElement>(element: T, children: U[]): Container<T, U[]>;
function create<T extends HTMLElement, U extends T[]>(element?: T, children?: U): Container<T, U> {
  return {
    element: element as T,
    children: children as U
  }
}

以上代码是一个重载函数的声明,函数重载允许一个函数接受不同数量或类型的参数时,作出不同的处理(PS:这里的处理就是会有不同的类型推断和约束)。

我们先一行一行的解析它的重载声明含义?

  • function create(): Container<HTMLDivElement, HTMLDivElement[]> 声明一个 create 函数,无入参,返回值是一个包含 HTMLDivElement 类型的 Container 类型数据。
  • function create<T extends HTMLElement>(element: T): Container<T, T[]> 声明一个 create 函数,接收一个被约束为 HTMLElement 类型的 element 参数(通过下图可以看出,像这些DOM类型可以满足 HTMLElement 类型约束),返回值是一个包含满足 HTMLElement 类型的 Container 类型数据。

关于对TypeScript泛型参数的默认值理解

  • function create<T extends HTMLElement, U extends HTMLElement>(element: T, children: U[]): Container<T, U[]> 声明一个 create 函数,接收被同样约束为 HTMLElement 类型的 elementchildren 参数。

好了,现在我们来一些测试函数来验证一下以上重载函数的类型推断:

const r1 = create() // Container<HTMLDivElement, HTMLDivElement[]>
const r2 = create(document.createElement('dialog')) // Container<HTMLDialogElement, HTMLDialogElement[]>
const children = [document.createElement('div')] // HTMLDivElement[]
const r3 = create(document.createElement('dialog'), children) // Container<HTMLDialogElement, HTMLDivElement[]>

关于对TypeScript泛型参数的默认值理解

根据图例,可以看出根据不同的入参个数及入参类型,所推断的函数返回值是跟上面的重载声明一一对应的,这就是 TypeScript 中最基础的函数重载的理解。看到这里,相信有很多人会有疑问,一个函数重载写这么多行声明,需要搞这么麻烦?,TS……劳资不学了??。

泛型参数的默认值——正文

由于前面的那么多铺垫,这篇文章的主题部分已经可以一带而过了~

有了泛型参数默认类型,我们可以将上面复杂的重载声明简化为这样?

function create<T extends HTMLElement = HTMLDivElement, U = T[]>(element?: T, children?: U): Container<T, U> {
  return {
    element: element as T,
    children: children as U
  }
}

没错,通过给泛型参数设置默认值,我们只需要写一个普通函数就行了,先看下代码执行效果:

关于对TypeScript泛型参数的默认值理解

我们给 T 设置了一个默认类型 HTMLDivElement 。在解析 create() 语句时,由于没有入参,T 的类型被赋为 HTMLDivElement,而 U = T[],所以 U 的类型是 HTMLDivElement[] ,因此最后的返回值类型推断为 Container<HTMLDivElement, HTMLDivElement[]> 。后续的 r2r3 都是同理。

这里的核心理解要点就是:这里的 T extends HTMLElement = HTMLDivElement, U = T[] 是默认值,只有没传参的时候会生效,如果传参了会被具体的入参类型所替换。

以上便是我对于 TypeScript 中泛型参数默认值的一些粗浅理解,欢迎讨论指正??。

参考

TypeScript 2.3——泛型参数默认值

到此这篇关于对TypeScript泛型参数的默认值理解的文章就介绍到这了,更多相关TS泛型参数默认值内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
js 表单验证方法(实用)
Apr 28 Javascript
解决表单中第一个非隐藏的元素获得焦点的一个方案
Oct 26 Javascript
javascript 词法作用域和闭包分析说明
Aug 12 Javascript
css transform 3D幻灯片特效实现步骤解读
Mar 27 Javascript
jquery快捷动态绑定键盘事件的操作函数代码
Oct 17 Javascript
js每隔5分钟执行一次ajax请求的实现方法
Nov 27 Javascript
JS来动态的修改url实现对url的增删查改
Sep 05 Javascript
JS实现网页游戏中滑块响应鼠标点击移动效果
Oct 19 Javascript
Vue.js展示AJAX数据简单示例讲解
Mar 29 Javascript
vue mixins组件复用的几种方式(小结)
Sep 06 Javascript
微信小程序上传文件到阿里OSS教程
May 20 Javascript
JS检测浏览器开发者工具是否打开的方法详解
Oct 02 Javascript
vue递归实现树形组件
Jul 15 #Vue.js
VUE递归树形实现多级列表
Jul 15 #Vue.js
javascript进阶篇深拷贝实现的四种方式
Jul 07 #Javascript
js面向对象编程OOP及函数式编程FP区别
Jul 07 #Javascript
类和原型的设计模式之复制与委托差异
JS高级程序设计之class继承重点详解
Jul 07 #Javascript
JS class语法糖的深入剖析
Jul 07 #Javascript
You might like
多文件上载系统完整版
2006/10/09 PHP
随时给自己贴的图片加文字的php水印
2007/03/16 PHP
php cookie 作用范围?不要在当前页面使用你的cookie
2009/03/24 PHP
PHP解析url并得到url参数方法总结
2018/10/11 PHP
PHP操作XML中XPath的应用示例
2019/07/04 PHP
Laravel框架源码解析之反射的使用详解
2020/05/14 PHP
js 小数取整的函数
2010/05/10 Javascript
基于jquery的分页控件(C#)
2011/01/06 Javascript
完美兼容各大浏览器的jQuery仿新浪图文淡入淡出间歇滚动特效
2014/11/12 Javascript
node.js中的fs.writeFile方法使用说明
2014/12/14 Javascript
AngularJS数据源的多种获取方式汇总
2016/02/02 Javascript
用 Vue.js 递归组件实现可折叠的树形菜单(demo)
2017/12/25 Javascript
如何为你的JS项目添加智能提示与类型检查详解
2019/03/12 Javascript
node爬取新型冠状病毒的疫情实时动态
2020/02/06 Javascript
element-ui 实现响应式导航栏的示例代码
2020/05/08 Javascript
一篇文章让你搞懂JavaScript 原型和原型链
2020/11/23 Javascript
解决Django数据库makemigrations有变化但是migrate时未变动问题
2018/05/30 Python
详解Python3中的迭代器和生成器及其区别
2018/10/09 Python
pandas读取csv文件,分隔符参数sep的实例
2018/12/12 Python
使用Python脚本zabbix自定义key监控oracle连接状态
2019/08/28 Python
Python如何使用内置库matplotlib绘制折线图
2020/02/24 Python
查看已安装tensorflow版本的方法示例
2020/04/19 Python
Numpy中ndim、shape、dtype、astype的用法详解
2020/06/14 Python
Python Map 函数的使用
2020/08/28 Python
米兰网婚纱礼服法国网上商店:Milanoo法国
2016/08/20 全球购物
京东全球售:直邮香港,澳门,台湾,美国,澳大利亚等地区
2017/09/24 全球购物
资生堂英国官网:Shiseido英国
2020/12/30 全球购物
财务管理专业应届毕业生求职信
2013/09/22 职场文书
运动会通讯稿150字
2014/02/15 职场文书
乡镇食品安全责任书
2014/07/28 职场文书
2014年有孩子的离婚协议书范本
2014/10/08 职场文书
作弊检讨书
2015/01/27 职场文书
2015年财务人员个人工作总结
2015/07/27 职场文书
2016年员工政治思想表现评语
2015/12/02 职场文书
怎样写好工作计划
2019/04/10 职场文书
python DataFrame中stack()方法、unstack()方法和pivot()方法浅析
2022/04/06 Python