數(shù)組類型
1. 數(shù)組類型聲明
在前面數(shù)據(jù)類型已經(jīng)了解過,聲明數(shù)組類的方式有兩中, 一種字面量方式, 一種泛型方式(很像JavaScript構(gòu)造函數(shù))
例如:
// 字面量方式聲明數(shù)組
let myArr: string[] = ['hello', 'world']
let myArr2: number[] = [20,30]
// 內(nèi)置泛型方式
// 注釋Array<> 使用的是泛型的<> 不是構(gòu)造函數(shù)的()
let myArr3: Array<string> = ['hello', 'world']
let myArr4: Array<number> = [20,30]
還需要注意是字面量方式聲明數(shù)組類型, 類型不能寫在[]
內(nèi)部, 寫在內(nèi)部就變成元組類型
其實兩種聲明數(shù)組類型的方式本質(zhì)是 同一個
type[]
聲明的數(shù)組類型 只是Array<type>
聲明數(shù)組類型的簡寫方式
而Array
就很像上一節(jié)中通用類型中的Box
, 所以Array
本質(zhì)就是一個內(nèi)置的泛型類型
2. readonlyArray
只讀數(shù)組類型
TypeScript 除了Array<T>
類型 還具有一個ReadonlyArray<T>
類型,
ReadonlyArray
類型和Array
類型很相似,但它是一個特殊的類型,用于描述不應(yīng)該更改的數(shù)組
2.1 Array<T>
聲明數(shù)組
通過Array<T>
聲明的數(shù)組是可以修改的
let arr:string[] = ['無人機(jī)', '車輛','巡邏車']
let device: Array<string> = arr
console.log('device', device) // ['無人機(jī)', '車輛','巡邏車']
// 修改數(shù)組項
device[0] = '自行車'
console.log('device', device) // ["自行車", "車輛", "巡邏車"]
console.log(arr === device) // true
2.2 ReadonlyArray<T>
聲明數(shù)組
通過ReadonlyArray<T>
聲明的數(shù)組不能被修改
let arr:string[] = ['無人機(jī)', '車輛','巡邏車']
let device: ReadonlyArray<string> = arr
device[0] = '自行車' // error
// 類型“readonly string[]”中的索引簽名僅允許讀取
device.push('aa') // error
// 但是ReadonlyArray 類型的數(shù)組在新增時報錯
// 類型“readonly string[]”上不存在屬性“push”, 也及時沒有push方法耻讽。
很像對象的readonly
修飾符,它主要的作用就是提醒工具, 即當(dāng)我們看到一個通過ReadonlyArray
類型注釋的變量時,其實就是告知我們,這個數(shù)組不可修改
注意, 與Array類型不同, ReadonlyArray
只作為類型使用, 不能當(dāng)成構(gòu)造函數(shù)使用
// 報錯: ReadonlyArray 僅表示類型, 但是這里作為值使用
new ReadonlyArray('hello','world')
而Array
不僅僅是TypeScript中的類型, 還是JavaScript中的構(gòu)造函數(shù)
// ok
new Array('hello','world')
相反,我們可以將常規(guī)的Array
類型數(shù)組分配給ReadonlyArray
const roArray:ReadonlyArray<string> = ['red','green','blue']
2.3 ReadonlyArray<T>
簡寫方式
正如TypeScript為Array<Type>
提供了簡寫方式Type[]
TypeScript也為ReadonlyArray<Type>
提供了簡寫方式,寫法為readonly Type[]
例如:
let device: ReadonlyArray<string> = ['無人機(jī)', '車輛','巡邏車']
// 可以簡寫為
let device2: readonly string[] = ['無人機(jī)', '車輛','巡邏車']
3. 與對象readonly
屬性的不同
需要注意的是, 與readonly
屬性修飾符不同, 常規(guī)的Array
類型和ReadonlyArray
類型之間賦值是相反的
3.1 對象只讀屬性賦值
// 只讀屬性接口
interface RoName{
readonly name:string
}
// 常規(guī)屬性接口
interface Name{
name:string
}
// 聲明變量
let roName: RoName = {
name: '張三'
}
let uname: Name = {
name:'李四'
}
// 1. 將readonly name屬性值賦值給常規(guī)name屬性值, 完全ok
uname.name = roName.name
// 2. 將常規(guī)name屬性賦值給readonly name 屬性報錯
// 報錯: 無法分配name ,因為它是只讀屬性
roName.name = uname.name
3.2 只讀數(shù)組賦值
而Array
和ReadonlyArray
之間的賦值與常規(guī)屬性和readonly 屬性相互賦值完全相反
let x:readonly string[] = ['hello']
let y:string[] = ['world']
// 1. 可以將常規(guī)Array類型值賦值給ReadonlyArray 類型
x = y;
console.log('x',x)
// x ['world']
// 2.不能將ReadonlyArray類型分配給Array類型
y = x;
// 報錯:類型readonly string[]為只讀類型,不可分配給可變類型 string[]
總結(jié):
- 對象的普通屬性不可賦值給readonly只讀屬性
- 數(shù)組readonly只讀數(shù)組 不可賦值給常規(guī)數(shù)組
4. 元組類型
4.1 元組類型
元組類型是另外一種Array
類型, 它確切的知道自己包含多少元素,多少類型, 以及每一個元素類型和位置
// 類型別名定義元組類型
type StringNumberArray = [string,number]
這里 StringNumberArray
就是由string
和number
組成 的元組類型,
就像ReadonlyArray
在運(yùn)行時沒有表示, 但對TypeScript來說很重要,
對于類型系統(tǒng),元組類型是描述索引以及索引包含的類型所形成的數(shù)組,
示例中:
// 類型別名定義元組類型
type StringNumberArray = [string,number]
// 使用類型注釋
let arr:StringNumberArray;
let a = arr[0]
// let a: string
let b = arr[1]
// let b: number
根據(jù)元組類型索引0
對應(yīng)的值類型為string
, 索引1
對應(yīng)的值類型為number
類型
我們除了可以通過索引單個取值,還可以使用JavaScript的數(shù)組解構(gòu)來解構(gòu)元組
// 類型別名定義元組類型
type StringNumberArray = [string,number]
// 使用類型注釋
let arr:StringNumberArray;
let [a,b]= arr;
console.log(a)
// let a: string
console.log(b)
// let b: number
元組類型在大量基于約定 的API中很好用, 因為每個元素的含義都是顯而易見, 這就是的我們在解構(gòu)變量中可以靈活的命名變量
4.2 操作超過元組索引賦值
如果我們此時試圖獲取超過元組數(shù)量對應(yīng)的索引位置值時,會得到一個錯誤
// 類型別名定義元組類型
type StringNumberArray = [string,number]
// 使用類型注釋
let arr:StringNumberArray;
let c = arr[2]
// 長度為 "2" 的元組類型 "StringNumberArray" 在索引 "2" 處沒有元素
報錯:告訴我們,我們想獲取索引對于的值在元組類型上沒有元素
如果我們嘗試在超過元素數(shù)組對應(yīng)的索引位置賦值時,也會有相同錯誤
// 類型別名定義元組類型
type StringNumberArray = [string,number]
// 使用類型注釋
let arr:StringNumberArray;
arr[2] = 'hello'
// 長度為 "2" 的元組類型 "StringNumberArray" 在索引 "2" 處沒有元素官脓。
4.3 特殊的Array類型
除了那些長度檢查之外, 像這樣簡單的元組類型等價于Array為特定索引聲明屬性類型的版本, 同時length
屬性使用明確的數(shù)字文字類型聲明
// 元組類型
type StringNumberArray = [string, number]
// 特殊的Array類型
interface StringNumberObj {
length: 2
0: string
1: number
}
4.4 元組的可選屬性
元組元素可以通過在元素類型后面添加?
來表示可選屬性, 可選的元組元素只能出現(xiàn)在元組的末尾, 也同樣會影響length
// 可選元組類型
type OptionalTuple = [number,number, number?]
// 可選元組中可選元素可以選擇是否賦值
let arr:OptionalTuple = [10,20]
let arr2:OptionalTuple = [10,20,30]
// 解構(gòu)元組類型注釋的變量
const [x,y,z] = arr
console.log(x)
// const x: number
console.log(y)
// const y: number
console.log(z)
// const z: number | undefined
console.log(arr.length)
// (property) length: 2 | 3
示例中,固定的元素有固定的類型, 可選元素是聯(lián)合類型, 沒有值時為undefined
,
元組的長度也是2
或3
, 不是一個確定的長度
4.5 元組的剩余運(yùn)算符
元組也可以有剩余元素, 他們必須是數(shù)組/元組類型
type StringNumberBooleans = [string, number, ...boolean[]];
type StringBooleansNumber = [string, ...boolean[], number];
type BooleansStringNumber = [...boolean[], string, number];
說明:
-
StringNumberBooleans
元組,其前兩個元素分別是string
和number
,但后面可以有任意數(shù)量的boolean
-
StringBooleansNumber
元組陈哑,第一個元素是string
搜吧,中間任意數(shù)量的boolean
類型,但結(jié)尾必須是number
類型 -
BooleansStringNumber
元組,起始元素是任意數(shù)量的boolean類型,但結(jié)尾必須是
string和
number`類型坦胶。
注意,帶有剩余運(yùn)算符元素的元組沒有固定的長度, 它只有一組位于不同位置的知名元素
const a: StringNumberBooleans = ["hello", 1];
const b: StringNumberBooleans = ["beautiful", 2, true];
const c: StringNumberBooleans = ["world", 3, true, false, true, false, true];
剩余運(yùn)算符元素是任意個,當(dāng)然也包含0個, 因此類型中boolean類型的值可以沒有
4.6 元組的可選屬性與剩余元素的使用
TypeScript允許將元組和參數(shù)列表對應(yīng)起來,
function example(...args:[string,number,...boolean[]]){
const [name,version,input] = args
console.log('args',args)
// parameter) args: [string, number, ...boolean[]]
}
example('hello',10,true)
因為...arg
會將函數(shù)參數(shù)收集成為數(shù)組, 但這個數(shù)組必須符合元組類型
也就是說這個函數(shù)必須傳遞兩個參數(shù), 第一個為字符串類型,第二個為數(shù)字類型, 其余可以為任意多的布爾類型
其實示例中函數(shù)的寫法等價于如下寫法
function example(name:string,version:number,...input:boolean[]){
//...
}
當(dāng)你 想用給一個剩余參數(shù)獲取可變數(shù)量參數(shù)時, 這很方便
4.7 readonly 元組類型
元組類型也有readonly
只讀類型, 可以通過在元組前面添加readonly
修飾符來指定, 就像數(shù)組簡寫語法一樣
// 只讀元組類型
let arr: readonly [string,number] = ['hello', 20]
// 修改只讀元組類型
arr[0] = 'world'
// 無法分配到 "0" 透典,因為它是只讀屬性
在大多數(shù)代碼中, 元組往往被創(chuàng)建后并未修改, 此時元組類型注釋可以將readonly
作為很好的默認(rèn)設(shè)置
4.8 斷言數(shù)組變?yōu)樵M類型
使用as const
斷言的數(shù)組,TypeScript會將其推斷為readonly 元組類型
例如:
// TypeScript 將會推斷為普通數(shù)組類型 number[]
let arr = [3,4]
// let arr: number[]
// 正常賦值
arr[0] = 20
沒有類型注釋的數(shù)組會被TypeScript推斷為數(shù)組類型.
此時可以使用斷言, 將普通數(shù)組斷言為元組類型
// 使用斷言為const TypeScript將會推斷為readonly [3,4]元組類型
let arr = [3,4] as const
// let arr: readonly [3, 4]
// readonly 元組賦值報錯
arr[0] = 10
// 無法分配到 "0" ,因為它是只讀屬性