TypeScript编写自动创建长度固定数组的类型工具详解

目录
  • 前言
  • 代码
    • 判断 List 的长度是否等于 Len

前言

TypeScript 中,当需要一个长度固定的数组时,通常会想到使用元组来进行表示,不过相对于数组而言,元组的每个元素的类型都不必是一致的。

如果现在需要一个长度为 30,元素类型为 string 的数组类型,其实就是一个元组,如果直接手写出来,那也太麻烦了,本文因此有感而发,编写了自动创建的类型工具。

代码

首先,不管三七二十一,先把这个类型工具给定义出来:

type FixedArray = any

然后开始逐步分析,先从泛型下手:

  • 因为长度是可以指定了,所以必定接受一个泛型 Len 用于表示数组长度;
  • 而且因为是数组,必须得要指定数组的类型,所以还有一个数组类型的泛型 T
  • 因为 TypeScript 中的遍历生成,一般都是使用递归实现的,所以还得有第三个参数,用于接受上一次执行后得到的数组 List

综上,这个类型工具加上泛型之后,如下:

type FixedArray<T = any, Len extends number = 6, List extends Array<T> = []> = any

接下去的步骤就很简单了,判断 List 的长度是否等于 Len,是的话,就直接返回 List,不是的话,将 List 和一个新的元素组成新的数组,把这个数组作为泛型,传入递归调用的 FixedArray 即可。

判断 List 的长度是否等于 Len

思路很简单,关键点在于如何判断 List 的长度是否等于 Len

根据上面的定义,Lennumber 类型的字面量,对于字面量而言,若是使用 extends 判断其子类型,只有 never 和其本身能够满足,所以只要排除掉 Lennever 的情况,剩下的只要判断 List['length'] 是否 extends Len 即可。

还有一点,因为 Lenextends number 的,所以传入 number 也是合法的,但是会造成死循环,所以也需要排除掉 Lennumber 本身的情况,综上,判断 Len 是否是合法的 number 字面量的类型工具如下,比较简单,不在赘述:

//判断是否为 never 的类型工具
type IsNever<T> = [T] extends [never] ? true : false
// 用于判断两个泛型是否相同,只要一个泛型传入 Len, 零一个泛型传入 number,就能判断 Len 是否为 number 本身
type IsTypeSelf<TA, TB> = TA extends TB ? TB extends TA ? true : false : false
// 判断 Len 是否为合法的 number 字面量类型
type IslegalNumber<N> = IsNever<N> extends true ? false : IsTypeSelf<number, N> extends true ? false : true

那么在 FixedArray 中,先判断 Len 是否合法,不合法直接返回 List:

type FixedArray<T = any, Len extends number = 6, List extends Array<T> = []> =
    IslegalNumber<Len> extends false // 判断 Len 是否合法
    ? List
    : any

然后再判断 List['length'] 是否 extends Len 即可,如果是,返回 List,如果不是,将 List 和一个新的元素组成新的数组,把这个数组作为泛型,传入递归调用的 FixedArray

type FixedArray<T = any, Len extends number = 6, List extends Array<T> = []> =
    IslegalNumber<Len> extends false
    ? List
    : List['length'] extends Len // 判断 `List['length']` 是否等于 `Len`
    ? List // 是就返回 List 本身
    : FixedArray<T, Len, [...List, T]> // 不是就递归,注意传入的数组添加了新的元素 T

测试一下:

type FixedArrayInstance = FixedArray&lt;string, 30&gt;

可以看到,生成了一个长度为30,元组类型都为 string 的元组。

以上就是TypeScript编写自动创建长度固定数组的类型工具详解的详细内容,更多关于TypeScript自动创建长度固定数组的资料请关注我们其它相关文章!

(0)

相关推荐

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

    目录 泛型简介 举个 举个 泛型参数的默认值——函数重载 泛型参数的默认值——正文 参考 泛型简介 软件工程中,我们不仅要创建一致的定义良好的 API,同时也要考虑可重用性. 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能. 在像C# 和 Java 这样的语言中,可以使用 泛型 来创建可重用的组件,一个组件可以支持多种类型的数据. 这样用户就可以以自己的数据类型来使用组件. 举个 举个最简单的例子来理解泛型 function getVal(

  • TypeScript新语法之infer extends示例详解

    目录 正文 模式匹配 提取枚举的值的类型 总结 正文 我们知道,TypeScript 支持 infer 来提取类型的一部分,通过模式匹配的方式. 模式匹配 比如元组类型提取最后一个元素的类型: type Last<Arr extends unknown[]> = Arr extends [...infer rest,infer Ele] ? Ele : never; 比如函数提取返回值类型: type GetReturnType<Func extends Function> = F

  • react+typescript中使用echarts的实现步骤

    安装echarts npm install echarts --save 按需加载Echarts demo echarts.init() API文档 import * as echarts from 'echarts/core' import { BarChart, // 系列类型的定义后缀都为 SeriesOption LineChart, } from 'echarts/charts' import { TitleComponent, // 组件类型的定义后缀都为 ComponentOpti

  • TypeScript 泛型推断实现示例详解

    目录 前言 基础类型准备 最终使用的方式 基于Interface的实现 (失败了) 所有内容都基于type 实现 完整Demo 结束语 前言 最近做东西都在用ts,有时候写比较复杂的功能,如果不熟悉,类型写起来还是挺麻烦的.有这样一个功能,在这里,我们就不以我们现有的业务来举例了,我们还是已Animal举例,来说明场景.通过一个工厂来创建不同的动物实例.在这里我们借助泛型来实现类型的约束和动态推到指定类型. 基础类型准备 用一个枚举来定义Animal的类型 enum EAnimalType {

  • Typescript中使用引用路径别名报错的解决方法

    在TS中引用路径别名提示找不到模块或者相应的声明 1.ts中使用路径别名报错 在react中通常路径别名都是在webpack的webpack.config.js文件中配置的,但是在引入了ts之后,webpack中的路径别名引用失效了此时我们需要在跟src文件同级目录的tsconfig.json文件中添加配置: 注意要在compilerOptions中添加(webpack中的路径也需要配置) "compilerOptions": { "target": "e

  • Vue3+TypeScript+Vite使用require动态引入图片等静态资源

    问题:Vue3+TypeScript+Vite的项目中如何使用require动态引入类似于图片等静态资源! 描述:今天在开发项目时(项目框架为Vue3+TypeScript+Vite)需要 动态引入静态资源,也就是img标签的src属性值为动态获取,按照以往的做法直接是require引入即可,如下代码: <img class="demo" :src="require(`../../../assets/image/${item.img}`)" /> 写上后

  • TypeScript编写自动创建长度固定数组的类型工具详解

    目录 前言 代码 判断 List 的长度是否等于 Len 前言 在 TypeScript 中,当需要一个长度固定的数组时,通常会想到使用元组来进行表示,不过相对于数组而言,元组的每个元素的类型都不必是一致的. 如果现在需要一个长度为 30,元素类型为 string 的数组类型,其实就是一个元组,如果直接手写出来,那也太麻烦了,本文因此有感而发,编写了自动创建的类型工具. 代码 首先,不管三七二十一,先把这个类型工具给定义出来: type FixedArray = any 然后开始逐步分析,先从泛

  • 重学Go语言之数组的具体使用详解

    目录 什么是数组 数组的创建 访问数组的元素 数组的长度 如何遍历数组 数组的比较 查找数组中的元素 将数组作为函数参数 二维与多维数组 小结 什么是数组 什么是数组?数组是有固定长度的相同数据类型元素的集合, 如下图所示: 从数组的定义以及上面的示例图我们可以得到数组的三个特征: 固定长度,数组的长度在编译时就要确定. 每个元素的数据类型相同. 数组索引从0开始,索引的最大值为数组长度减1. 数组的创建 直接声明数组变量,在声明时必须指定长度: var iArray [2]int var sA

  • JavaScript 中有关数组对象的方法(详解)

    JS 处理数组多种方法 js 中的数据类型分为两大类:原始类型和对象类型. 原始类型包括:数值.字符串.布尔值.null.undefined 对象类型包括:对象即是属性的集合,当然这里又两个特殊的对象----函数(js中的一等对象).数组(键值的有序集合). 数组元素的添加 arrayObj.push([item1 [item2 [. . . [itemN ]]]]); 将一个或多个新元素添加到数组结尾,并返回数组新长度 arrayObj.unshift([item1 [item2 [. . .

  • c++ 数组定义及初始化详解

    C ++提供了一种数据结构,即数组,该数组存储一个固定大小的由相同类型元素构成的顺序集合. 数组中的元素存储在一个连续内存位置中,元素可通过数组索引访问, 最低地址对应于第一个元素,最高地址对应于最后一个元素. 声明数组 例如 声明固定长度的数组: const int Size = 5; int arr[Size] = {3, 6, 9, 12, 15}; arr[3] = 42; 注意:方括号[]中的内容(表示数组中元素的数量)必须是一个常量表达式,因为数组是静态内存块,必须在编译时确定大小,

  • Go语言基础数组用法及示例详解

    目录 概述 语法 注意 示例 概述 固定长度,数组声明后长度便不能再修改 只能存储一种特定类型元素的序列 语法 编号 方式 代码示例 1 直接声明 var arr [3]int 2 make arr:=make([]int,3) 3 字面量 arr:=[3]int{1,2,3} 4 自动识别长度 arr:=[-]int{1,2,3} 5 二维数组 arr := [4][4]int{{1}, {1, 2}, {1, 2, 3}} 6 new arrp := new([10]int) 7 下标取值

  • JavaScript中十种一步拷贝数组的方法实例详解

    JavaScript中我们经常会遇到拷贝数组的场景,但是都有哪些方式能够来实现呢,我们不妨来梳理一下. 1.扩展运算符(浅拷贝) 自从ES6出现以来,这已经成为最流行的方法.它是一个很简单的语法,但是当你在使用类似于React和Redux这类库时,你会发现它是非常非常有用的. numbers = [1, 2, 3]; numbersCopy = [...numbers]; 这个方法不能有效的拷贝多维数组.数组/对象值的拷贝是通过引用而不是值复制. // numbersCopy.push(4);

  • KnockoutJS数组比较算法实例详解

    这篇文章主要介绍了KnockoutJS数组比较算法实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前端开发中,数组是一种非常有用的数据结构.这篇博客会解释并分析KnockoutJS实现中使用的数据比较算法. 算法的目的 KnockoutJS使用MVVM的思想,view model中的数组元素会对应data model中的数组数据,当用户进行输入或者请求后台时,数组数据会发生变更, 从而带动UI的更新.例如购物车类的页面,用户可以通过点击

  • Redis数组和链表深入详解

    1.数组和链表基础知识 数组: 数组会在内存中开辟一块连续的空间存储数据,这种存储方式有利也有弊端.当获取数据的时候,直接通过下标值就可以获取到对应的元素,时间复杂度为O(1).但是如果新增或者删除数据会移动大量的数据,时间复杂度为O(n).数组的扩容机制是:如果数组空间不足,会先开辟一块新的空间地址,将原来的数组复制到新的数组中. 链表: 链表不需要开辟连续的内存空间,其通过指针将所有的数据连接起来.新增或者删除的时候只需要将指针指向的地址修改就行了,时间复杂度为O(1).但是查询的时间复杂度

  • java数组算法例题代码详解(冒泡排序,选择排序,找最大值、最小值,添加、删除元素等)

    数组算法例题 1.数组逆序 第一个和最后一个互换,第二个和倒数第二个互换,就相当于把数组想下图一样,进行对折互换,如果数组个数为奇数,则中间保持不变其余元素互换即可 import java.util.Arrays; class Demo12 { public static void main (String[] args) { int[] arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; System.out.println(Arrays.toString(arr));

  • ECMAScript 6数组的扩展实例详解

    目录 扩展运算符 Array.from() Array.of() 数组实例的 copyWithin() 数组实例的 find() 和 findIndex() 数组实例的 fill() 数组实例的 includes() 扩展运算符 扩展运算符(spread)是三个点(...).它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列. console.log(...[1, 2, 3]) // 1 2 3 console.log(1, ...[2, 3, 4], 5) // 1 2 3 4

随机推荐