ts世界中的数组类型,元组类型,readonly元组类型

168 阅读5分钟

数组类型

js世界:数组是一种特殊的对象, 其特点:元素的类型是任意的, 数组长度的是任意的

ts世界:用js数组转换为的ts数组类型的表示: (联合类型)[ ]

const a = [1, 2, 3]

const b = [true, 'hello']

const c = [true, 1, 'hello']

type ta = typeof a;
//type ta = number[]

type tb = typeof b;
//type tb = (string | boolean)[]

type tc = typeof c;
//type tc = (string | number | boolean)[]

可以看到ts中ta的类型是number[], tb的类型是(string | boolean)[], tc的类型是(string | boolean | number)[]

(上难度了(^_^))加点ts的类型操作符

First作用:返回数组类型中的第一个属性的属性值
type First<T extends any[]> = T extends [] ? never : T[0]

type tpa = First<ta>
//type tpa = number

type tpb = First<tb>
//type tpb = string | boolean

type tpc = First<tc>
//type tpc = string | number | boolean
为什么T[0] 会返回这个结果?

我是怎么理解的,对于一个js世界的数组来说:元素的类型是任意的, 数组长度的是任意的, 数组本质是对象,可以log一下:(下面为简写代码)

const a = [1, 2, 3, ,true, 'hello']
ogj = {
	0 : 1,
	1 : 2,
	3 : 3 ,
	4 : 'hello'
	... more others attributes
	
	原生链上的属性:
	length:5
}
特定的js数组 转换 ts类型如何表达它独有的性质

那么在typeof 将一个数组转换为ts世界的类型的时候,以:const a = [1, 2, 3 ,true, 'hello'], type ta = typeof a为例子,那么ta这个类型怎么准确的表达出a这个数组的性质 ?ta:(string | number | boolean)[] ,请看下一段的代码:


const a = [1, 2, 3, true, 'hello']
type First1<T extends any[]> = T extends [] ? never : T[1]
type First2<T extends any[]> = T extends [] ? never : T[2]
type First3<T extends any[]> = T extends [] ? never : T[100000]
type First4<T extends any[]> = T extends [] ? never : T['length']

type ta = typeof a;
//type ta = (string | number | boolean)[]

type tpa = First1<ta>
//type pa = string | number | boolean
type tpb = First2<ta>
//type tpb = string | number | boolean
type tpc = First3<ta>
//type tpc = string | number | boolean
type tpd = First4<ta>
//type tpd = number

注解:方括号运算符([])用于取出对象的键值类型,比如T[K]会返回对象T的属性K的类型

a数组的每一个元素的类型可以是(string | number | boolean)中的一个,同时由于数组元素长度是任意的 ,所以T[10000] 里面填多少个0,a数组类型的元素类型都是string | number | boolean,而length这个键值毫无疑问是number类型,

(js世界所有都是对象,同理ts世界的类型也应该是对象的设计方式)其实==从对象类型(interface类型)的角度去理解ts的数组类型==更好:(下面为简码)

type ta maybe是:
{
	0 ~ 无穷: string | number | boolean
	length: number
	other more attribute
	...
}

元组类型Tuple 是一种特殊的数组类型

元组类型是在TypeScript(JavaScript的一个超集)中引入的一个新类型,用于表示一个已知元素数量和类型的数组。每个元素的类型都是固定的, ==元组类型是一种特殊的数组类型==,

//定了一个元组类型
type a = [1, 2, 3]

const an: a = [1, 2, 3] //ok
const aerror: a = [1, 2] //Error
//Type '[1, 2]' is not assignable to type 'a'.

type b = [string, number];

const bn : b = ['hello', 10]; // OK
const berror: b = ['hello', true]; // Error
//Type 'boolean' is not assignable to type 'number'.

从interface类型去理解,元组类型:

type a = [1, 2, 3]

//可以理解为
type a = {
	0 : 1,
	1 : 2,
	3 : 3,
	lenght : 3
	...
}

那么
const aerror: a = [1, 2] //Error
错误就变成可以理解了,因为只有第一个和第二个键值对符合

readonly元组类型(只读元组类型)

在ts世界中,你可以使用readonly修饰符来创建一个只读的元组类型。==一旦一个只读元组被初始化,它的元素就不能被改变==。这是一个只读元组的例子:

const tuple: readonly [number, string] = [1, 'hello'];

type c = readonly [1, 2, 3]
const tc:c = [1, 2, 3]; 
//ts的数组元素将不能修改了

记住一个区别:

const a = [1, 2, 3] as const;
const b = [1, 2, 3]

type ta = typeof a;
//type ta = readonly [1, 2, 3]
type tb = typeof b;
//type tb = number[]

a声明里面的元素每一个元素都是不可变的,那么的它的typeof 是readonly [1, 2, 3], 而b只是一个普通的数组,数组类型就是number[]

测试一下:

类型猜猜猜

1.
type a = [1, 2, 3];
a 是一种元组类型,[1, 2, 3];

2.
const b = [1, 2, true, , 'hello world'];
type tb = typeof b;
tb 是一种数组类型,(string | number | boolean | undefined)[]

3.
type c = [1, 2, true, 'hello world'];
c 是一种元组类型,[1, 2, true, 'hello world'];

4.
type d = readonly [1, 2, 3];
d 是一种readonly元组类型 readonly[1, 2, 3];

5.
const e = [1, 2, true, 'hello'] as const;
type f = typeof e;
f 是一种readonly元组类型,readonly[1, 2, true, 'hello']

传入测试:

type First1<T extends readonly any[]> = T extends [] ? never : T[0]

1.
type a = First1<[3, 2, 1]>
[3, 2, 1]以元组类型传入,第一个元素的键值为3,所以返回3

2.
const b = [1, 2, 3]
// @ts-expect-error
type c = First1<a> //error
Type 'number' does not satisfy the constraint 'any[]'
js的数组和ts的类型操作注定不同

3.
const c = [1, 2, 3]
type d = First1<typeof c>
传入的为数组类型number[],所以返回的是number类型

4.
const e = ["hello word", 1, 2, 3] as const
type f = First1<typeof e> //erroe
The type 'readonly ["hello word", 1, 2, 3]' is 'readonly' and cannot be assigned to the mutable type 'any[]'
可以改:T extends any[] ===》T extends readonly any[]

参考:

如有错误,烦请私信