1. 變量的類型注釋
在JavaScript中, 變量的復(fù)制相對(duì)靈活, 除了const
外, let
和var
聲明的變量可以賦予不同類型的數(shù)據(jù)
例如:
let val = 'string'
console.log(typeof val)
// 變量val的類型為string 類型
val = 10
console.log(typeof val)
// 變量val的類型為number 類型
val = true
console.log(typeof val)
// 變量val的類型為boolean 類型
示例中, 變量val
可以賦值不同類型的變量, 而變量的類型取決于賦予變量的值.
如果我們需要限定變量的類型, 只允許給變量賦予某一種類型或幾種基本類型 的聯(lián)合類型, 我們就需要使用TypeScript給變量添加類型注釋
1.1 賦初值
基礎(chǔ)變量聲明的語(yǔ)法
let [變量]:[類型注釋] = 值
類型注釋需要用來(lái)描述變量可以被賦予那些類型的值.
// 1. 這樣會(huì)報(bào)錯(cuò),聲明的變量是number類型,卻被賦值為string類型的值
let a:number = 'hello'
// 2. 這樣也會(huì)報(bào)錯(cuò),聲明string類型后中途重新賦值了其他類型的值
let a:number = 20
a = 'hello'
這種方式實(shí)現(xiàn)的變量命名的好處,那就是在賦值的時(shí)候確定變量的類型,如果存值和聲明的變量類型不符合就會(huì)報(bào)錯(cuò)
聲明類型的變量,將只能賦予相同類型的值
如果聲明變量賦初始值,在大多數(shù)情況下,添加類型注釋并不是必須的, 原因在與TypeScript會(huì)根據(jù)我們賦予的初始值來(lái)自動(dòng)推斷變量的類型.
例如:
let a = 'hello'
// let a: string
a = 10
// 不能將類型“number”分配給類型“string”
TypeScript更加初始賦值'hello'
推斷變量a
為string
類型, 此時(shí)在將其他類型數(shù)據(jù)賦值給變量a
就會(huì)報(bào)錯(cuò)
1.2 不賦初始值
語(yǔ)法
let [變量]:[類型注釋]
- 如果只創(chuàng)造了變量并規(guī)定類型,那么這個(gè)變量默認(rèn)值就是undefined
- 如果后面需要賦值時(shí),還是只能按照 聲明的變量類型來(lái)賦值,否則就會(huì)出錯(cuò)
let num:number;
console.log(num) // undefined
num = 10 // ok
num = 'hello'
// 錯(cuò)誤:不能將類型“string”分配給類型“number”
聲明一個(gè)變量不管什么類型, 初始不賦值,變量默認(rèn)為undefined
,這是遵循JavaScript的語(yǔ)言規(guī)范,
那么為什么undefined
類型的值可以賦值給number
類型的值呢? 那么先來(lái)了解一下TypeScript類型
2. 數(shù)據(jù)類型
TypeScript支持與JavaScript幾乎相同的數(shù)據(jù)類型阴绢,此外還提供了實(shí)用的枚舉類型方便我們使用霜第。
TypeScript 數(shù)據(jù)類型有:
- 數(shù)字類型 number
- 字符串類型 string
- 布爾類型 boolean
- undefined undefined
- null null
- 數(shù)組類型 []
- 元組 []
(數(shù)組的特殊形式)
- 對(duì)象類型 {}
- 函數(shù)類型 Function
- 任意類型 any
- void void
- never never
- unknown 不認(rèn)識(shí),代表 任何值,類似于any
- 枚舉 enum
2.1 字符串,數(shù)字,布爾類型
和JavaScript 字符串,數(shù)字,布爾類型一樣掐禁,并且所有數(shù)字都是浮點(diǎn)數(shù)。以及可以使用ES6字符串模板
// 字符串類型
let username = '張三'
let person :string = `字符串模板${username}`
console.log('person', person)
// 數(shù)字類型
let num: number = 30
console.log('num', num)
// 布爾類型
let bol: boolean = true;
console.log('bol',bol)
2.2 數(shù)組類型
JavaScript定義數(shù)組可以通過(guò)字面量和構(gòu)造函數(shù), TypeScript在添加數(shù)組的類型注釋也不同的方式
第一種就是使用字面量的方式
// 正確的寫(xiě)法
let arr: number[] = [10, 20, 30, 40];
let arr: string[] = ['a', 'b', 'c', 'd'];
// ...
// 錯(cuò)誤的寫(xiě)法
let arr:[number] = [10, 20, 30, 40];
// 這種寫(xiě)法指表示確定數(shù)組第一項(xiàng)的數(shù)據(jù)類型,其他的沒(méi)有確定,報(bào)錯(cuò)
number[]
這種數(shù)組類型的定義方式, 其中[]
表示是數(shù)組類型,number
是基本數(shù)據(jù)類型, 表示數(shù)組每一項(xiàng)都是number
類型
第二種:使用內(nèi)置的泛型Array
// 或者使用泛型
let arr: Array<number> = [10, 20, 30, 40];
let arr: Array<string> = ['a', 'b', 'c', 'd'];
// ...
上面的示例中數(shù)組內(nèi)所有的值都是同一種類型, 但在很多情況下數(shù)組內(nèi)會(huì)有不同數(shù)據(jù)類型的值,
那么就可以使用any
類型或聯(lián)合類型
使用any
類型定義數(shù)組內(nèi)的元素類型
let arr: any[]= [10, 'hello', true, null];
let arr: Array<any> = [10, 'hello', true, null];
// any表示任意類型,表示數(shù)組內(nèi)每一項(xiàng)都可以是任意類型
使用聯(lián)合類型數(shù)組, 聯(lián)合類型使用|
符合,
聯(lián)合類型的前提是你明確的知道,數(shù)組內(nèi)只能存那些類型的數(shù)據(jù)
例如:我們希望一個(gè)數(shù)組只能存number
,string
兩種類型的值
let arr:(string | number)[] = ['hello' , 20, 'world']
let arr:Array<string | number> = ['hello' , 20, 'world']
(string | number)[]
類型注釋中[]
表示為數(shù)組類型,(string | number)
就是聯(lián)合類型,表示數(shù)組沒(méi)一項(xiàng)可以是string
類型或number
類型.滿足一個(gè)即可
2.3 元組類型
元組類型其實(shí)就是另外一種Array
數(shù)組 類型. 它確切的知道數(shù)組中包含多少元素, 以及它在特定位置包含哪些類型
元組類型表示一個(gè)已知元素?cái)?shù)量和每一項(xiàng)類型的數(shù)組,各元素的類型不必相同
其實(shí)元祖類型就是單獨(dú)定義數(shù)組的每一個(gè)數(shù)據(jù)的類型.
// 正確的寫(xiě)法
let arr:[number,string, boolean] = [10,'string',true]
// 錯(cuò)誤的寫(xiě)法
let arr:[string,string, boolean] = [10,'string',true]
// 編譯時(shí)報(bào)錯(cuò),Type 'number' is not assignable to type 'string'.
// 不能將數(shù)字類型的值賦值給字符串類型
// 注意定義數(shù)據(jù)類型和數(shù)據(jù)的數(shù)量保持一致, 數(shù)量不同則會(huì)報(bào)錯(cuò)
let arr:[string,string, boolean] = [10,'string']
// Property '2' is missing in type '[string, number]' but required in type '[string, number, boolean]'.
也可以先聲明元組類型的變量,之后再重新賦值
let a:[string,number,number,boolean,object]
// 這種 寫(xiě)法沒(méi)問(wèn)題
a = ["hello",1,2,true,{age: 18}];
// 這種寫(xiě)法不行,上面創(chuàng)建變量時(shí),要求的類型和值的類型按照順序?qū)Σ簧?a = [1, "hello" , 2, true,{age: 18}];
// 這個(gè)寫(xiě)法也不可以,因?yàn)樯倭艘粋€(gè)對(duì)象
a = ["hello",1,2, true];
TypeScriptde的一個(gè)好處就是,會(huì)在代碼執(zhí)行前的類型檢查階段拋出錯(cuò)誤, 不想JavaScript只能在代碼運(yùn)行時(shí),才知道發(fā)生了什么錯(cuò)誤
2.4 object 引用數(shù)據(jù)類型
object
是一個(gè)特殊的類型, 指定是任何不是原始值(string, number,bigint,boolean,symbol,null, undefined)的值.
這與空對(duì)象類型{}
不同, 也與全局類型Object
不同
object
表示的是JavaScript中的引用類型,只要是具有屬性的類型都可以使用object
類型
// 函數(shù)
const fn:object = () => console.log('fn')
// 數(shù)組
const arr:object = [10,20]
// 對(duì)象
const obj:object = {name:'hello', age:18}
因此這個(gè)類型在使用很少, 大多通過(guò)更詳細(xì)的類型添加類型注釋.
例如:
// 函數(shù)類型注釋
const fn:() => void = () => console.log('fn')
// 數(shù)組類型注釋
const arr:number[] = [10,20]
// 對(duì)象
const obj:{name:string,age:number} = {name:'hello', age:18}
2.5 對(duì)象類型
除了基本數(shù)據(jù)類型, 最常見(jiàn)的類型是對(duì)象類型. 對(duì)象類型是值任何帶有屬性的JavaScript值
對(duì)象類型幾乎是所有的屬性都要定義對(duì)象類型.
通過(guò)關(guān)鍵字object
定義對(duì)象類型
// 對(duì)象類型
let ob:object = { a: 10 }
這種類型注釋的對(duì)象并不限定屬性數(shù)量與屬性值的類型. 可以賦值任意類型
也可以通過(guò)字面量方式,列出所有屬性以及屬性類型來(lái)進(jìn)行類型注釋
let student:{name:string,age:number} = {name:'張三',age:18}
2.6 Function 類型
Function
為全局類型, 描述JavaScript中所有函數(shù)值的屬性, Function
類型總是可以調(diào)用類型值的特殊屬性, 這些調(diào)用返回any
, 一般也不常用
function example(fn:Function){
return fn(1,2)
}
參數(shù)fn
是一個(gè)具有函數(shù)屬性的函數(shù)類型, fn()
的調(diào)用是一個(gè)無(wú)類型的函數(shù)調(diào)用, 因?yàn)榉祷仡愋蜑?code>any類型不太安全.最好避免使用,.
可以使用更加詳細(xì)的函數(shù)類型注釋
例如:
function example(fn:() => void){
return fn(1,2)
}
2.7 任意類型 any
TypeScript也有一個(gè)特殊的類型: any
類型,當(dāng)你不希望某個(gè)特定的值導(dǎo)致類型檢查錯(cuò)誤時(shí),可以使用它
通常當(dāng)你聲明一個(gè)變量, 沒(méi)有確定初始類型,也沒(méi)有賦初始值是,或者賦初值為undefined或null時(shí), 變量的類型默認(rèn)為any
類型.
也就是說(shuō):當(dāng)您不指定類型,并且 TypeScript 無(wú)法從上下文中推斷出它時(shí),編譯器通常會(huì)默認(rèn)為any
.
any
類型的變量賦值任何類型的數(shù)據(jù)都不會(huì)報(bào)錯(cuò)
let a = null
// 或者
let a = undefined
// 或者
let a;
// let a: any
a = 'aa'
console.log(a) // 'aa'
a = 30
console.log(a) // 30
一般來(lái)說(shuō)并不建議大量使用any
類型.當(dāng)你明確知道一個(gè)變量之后不會(huì)被賦予其他類型的數(shù)據(jù), 那么就可以在聲明變量時(shí)添加詳細(xì)的類型注釋;
只有當(dāng)你在不確定變量未來(lái)會(huì)賦予什么樣類型的值時(shí), 可以嘗試使用
注意:
any類型的變量會(huì)跳過(guò)類型檢查
例如:
let obj: any = { x: 0 };
// 下面代碼將沒(méi)有一行代碼編譯錯(cuò)誤
obj.foo();
obj();
obj.bar = 100;
obj = "hello";
const n: number = obj;
實(shí)例中變量obj
為any
類型, 因此obj
身上的所有操作都會(huì)跳過(guò)類型檢查, 因此在TypeScript編譯代碼時(shí)不會(huì)報(bào)錯(cuò).
但是執(zhí)行編譯后的代碼可能會(huì)出錯(cuò).
2.8 空類型 void undefined null
Void 表示沒(méi)有任何類型 空
通常聲明一個(gè)Void 類型沒(méi)什么意義,因?yàn)檫@個(gè)類型的變量只能賦值為undefined和null
let a: void = undefined;
console.log(a)
let a: void = null;
console.log(a)
// 賦值其他類型的值就會(huì)報(bào)錯(cuò)
let a: void = 123;
console.log(a)
// 報(bào)錯(cuò):不能將類型“number”分配給類型“void”
在TypeScript里,undefined和null 兩者各自都有自己類型分別叫做undefined和null;和void相似,他們的類型本身用處不大:
// 聲明一個(gè)undefined類型變量
let und: undefined;
und = undefined;
und = null;
console.log(und)
// 聲明一個(gè)null類型的變量
let nul: null
nul = null;
und = undefined;
console.log(nul)
和void
一樣, undefined
和null
類型只能賦值undefined
或null
值, 本身意義不大
默認(rèn)情況下,null和undefined 是 所有類型的子類型
就是說(shuō)你可以把null和undefined賦值給其他類型的變量
let num:number = undefined;
let num:number = null;
let str:string = undefined;
// ....
但是,不能將其他類型的值賦值給void,undefined,null類型的變量
let un:undefined = 12;
let aa:null = 'aa';
let bb:void = true;
這樣寫(xiě)會(huì)報(bào)錯(cuò)
2.9 never類型
never類型表示的是那些永不存在的值的類型
這個(gè)嚴(yán)格來(lái)說(shuō)算不上新的數(shù)據(jù)類型,只是開(kāi)發(fā)者對(duì)于一些值所起的作用的判斷而已
比如:
- 總是會(huì)拋出異常,throw錯(cuò)誤或是返回一個(gè)error類型的數(shù)據(jù)
- 根本就不會(huì)有返回值的函數(shù)表達(dá)式(死循環(huán)函數(shù))
// 沒(méi)有返回值
function error(msg:string):never {
throw new Error(msg)
}
// 一旦有了返回值never類型就報(bào)錯(cuò)
function error():never {
retrun new Error('something failed')
}
// 報(bào)錯(cuò): 不能將類型“Error”分配給類型“never”。
// 哪怕沒(méi)有顯示的return 也會(huì)報(bào)錯(cuò), 因?yàn)楹瘮?shù)有默認(rèn)返回undefined
function error():never {
new Error('something failed')
}
// 返回“never”的函數(shù)不能具有可訪問(wèn)的終結(jié)點(diǎn)疆拘。
// 死循環(huán)函數(shù)
function infiniteLoop():never{
while(true){
console.log('帥")
}
}
never類型是任何類型的子類型,任何其他類型的值都不能賦值給never
類型.即使any也不可以
let n:never;
n = 12
// 不能將類型“number”分配給類型“never”
2.10 unknown 類型
unknown
類型代表任何值, 這類似于any
類型, 但更安全, 因?yàn)橛弥底鋈魏问虑槎际遣缓戏ǖ?/p>
例如:
function fn1(a:any){
// 調(diào)用any類型的屬性是合法的
// 任意類型有可能是對(duì)象類型
a.b()
}
function fn2(a:unknown){
// unknown 未知類型, 不確定它是什么值
a.b()
// 報(bào)錯(cuò):類型“unknown”上不存在屬性“b”。
}
2.11 枚舉類型
枚舉類型是TypeScript添加到JavaScript的一項(xiàng)功能, 它允許描述一個(gè)值, 該值可能是一組可能的命名常量之一.
與大多數(shù)TypeScript功能不同,這不是對(duì)JavaScript的類型級(jí)添加, 而是添加到語(yǔ)言和運(yùn)行時(shí)的東西.
詳細(xì)內(nèi)容稍后章節(jié)介紹