第一節(jié):TypeScript變量與數(shù)據(jù)類型

1. 變量的類型注釋

在JavaScript中, 變量的復(fù)制相對靈活, 除了const外, letvar聲明的變量可以賦予不同類型的數(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ǔ)變量聲明的語法
let [變量]:[類型注釋] = 值

類型注釋需要用來描述變量可以被賦予那些類型的值.

// 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ù)我們賦予的初始值來自動(dòng)推斷變量的類型.

例如:

let a = 'hello'
// let a: string

a =  10
// 不能將類型“number”分配給類型“string”

TypeScript更加初始賦值'hello'推斷變量astring類型, 此時(shí)在將其他類型數(shù)據(jù)賦值給變量a就會(huì)報(bào)錯(cuò)

1.2 不賦初始值

語法
let [變量]:[類型注釋]

  1. 如果只創(chuàng)造了變量并規(guī)定類型,那么這個(gè)變量默認(rèn)值就是undefined
  2. 如果后面需要賦值時(shí),還是只能按照 聲明的變量類型來賦值,否則就會(huì)出錯(cuò)
let num:number;
console.log(num)  // undefined

num = 10  // ok

num = 'hello'
// 錯(cuò)誤:不能將類型“string”分配給類型“number”

聲明一個(gè)變量不管什么類型, 初始不賦值,變量默認(rèn)為undefined,這是遵循JavaScript的語言規(guī)范,

那么為什么undefined類型的值可以賦值給number類型的值呢? 那么先來了解一下TypeScript類型


2. 數(shù)據(jù)類型

TypeScript支持與JavaScript幾乎相同的數(shù)據(jù)類型,此外還提供了實(shí)用的枚舉類型方便我們使用。

TypeScript 數(shù)據(jù)類型有:

  1. 數(shù)字類型 number
  2. 字符串類型 string
  3. 布爾類型 boolean
  4. undefined undefined
  5. null null
  6. 數(shù)組類型 []
  7. 元組 [] (數(shù)組的特殊形式)
  8. 對象類型 {}
  9. 函數(shù)類型 Function
  10. 任意類型 any
  11. void void
  12. never never
  13. unknown 不認(rèn)識,代表 任何值,類似于any
  14. 枚舉 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ù)組可以通過字面量和構(gòu)造函數(shù), TypeScript在添加數(shù)組的類型注釋也不同的方式

第一種就是使用字面量的方式

// 正確的寫法
let arr: number[] = [10, 20, 30, 40];

let arr: string[] = ['a', 'b', 'c', 'd'];
// ...

// 錯(cuò)誤的寫法
let arr:[number] = [10, 20, 30, 40];
// 這種寫法指表示確定數(shù)組第一項(xiàng)的數(shù)據(jù)類型,其他的沒有確定,報(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ù)組沒一項(xiàng)可以是string類型或number類型.滿足一個(gè)即可


2.3 元組類型

元組類型其實(shí)就是另外一種Array數(shù)組 類型. 它確切的知道數(shù)組中包含多少元素, 以及它在特定位置包含哪些類型

元組類型表示一個(gè)已知元素?cái)?shù)量和每一項(xiàng)類型的數(shù)組,各元素的類型不必相同

其實(shí)元祖類型就是單獨(dú)定義數(shù)組的每一個(gè)數(shù)據(jù)的類型.

// 正確的寫法
let arr:[number,string, boolean] = [10,'string',true]

// 錯(cuò)誤的寫法
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]

// 這種 寫法沒問題
a =  ["hello",1,2,true,{age: 18}];

// 這種寫法不行,上面創(chuàng)建變量時(shí),要求的類型和值的類型按照順序?qū)Σ簧?a = [1, "hello" , 2, true,{age: 18}];

// 這個(gè)寫法也不可以,因?yàn)樯倭艘粋€(gè)對象
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)的值.

這與空對象類型{}不同, 也與全局類型Object不同

object表示的是JavaScript中的引用類型,只要是具有屬性的類型都可以使用object類型

// 函數(shù)
const fn:object = () => console.log('fn')

// 數(shù)組
const arr:object = [10,20]

// 對象
const obj:object = {name:'hello', age:18}

因此這個(gè)類型在使用很少, 大多通過更詳細(xì)的類型添加類型注釋.

例如:

// 函數(shù)類型注釋
const fn:() => void = () => console.log('fn')

// 數(shù)組類型注釋
const arr:number[] = [10,20]

// 對象
const obj:{name:string,age:number} = {name:'hello', age:18}


2.5 對象類型

除了基本數(shù)據(jù)類型, 最常見的類型是對象類型. 對象類型是值任何帶有屬性的JavaScript值

對象類型幾乎是所有的屬性都要定義對象類型.

通過關(guān)鍵字object定義對象類型

// 對象類型
let ob:object =  { a: 10 }

這種類型注釋的對象并不限定屬性數(shù)量與屬性值的類型. 可以賦值任意類型

也可以通過字面量方式,列出所有屬性以及屬性類型來進(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è)無類型的函數(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è)變量, 沒有確定初始類型,也沒有賦初始值是,或者賦初值為undefined或null時(shí), 變量的類型默認(rèn)為any類型.

也就是說:當(dāng)您不指定類型,并且 TypeScript 無法從上下文中推斷出它時(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

一般來說并不建議大量使用any類型.當(dāng)你明確知道一個(gè)變量之后不會(huì)被賦予其他類型的數(shù)據(jù), 那么就可以在聲明變量時(shí)添加詳細(xì)的類型注釋;

只有當(dāng)你在不確定變量未來會(huì)賦予什么樣類型的值時(shí), 可以嘗試使用

注意:

any類型的變量會(huì)跳過類型檢查

例如:

let obj: any = { x: 0 };

// 下面代碼將沒有一行代碼編譯錯(cuò)誤
obj.foo();
obj();
obj.bar = 100;
obj = "hello";
const n: number = obj;

實(shí)例中變量objany類型, 因此obj身上的所有操作都會(huì)跳過類型檢查, 因此在TypeScript編譯代碼時(shí)不會(huì)報(bào)錯(cuò).

但是執(zhí)行編譯后的代碼可能會(huì)出錯(cuò).

2.8 空類型 void undefined null

Void 表示沒有任何類型 空
通常聲明一個(gè)Void 類型沒什么意義,因?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一樣, undefinednull類型只能賦值undefinednull值, 本身意義不大

默認(rèn)情況下,null和undefined 是 所有類型的子類型
就是說你可以把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;

這樣寫會(huì)報(bào)錯(cuò)

2.9 never類型

never類型表示的是那些永不存在的值的類型
這個(gè)嚴(yán)格來說算不上新的數(shù)據(jù)類型,只是開發(fā)者對于一些值所起的作用的判斷而已

比如:

  1. 總是會(huì)拋出異常,throw錯(cuò)誤或是返回一個(gè)error類型的數(shù)據(jù)
  2. 根本就不會(huì)有返回值的函數(shù)表達(dá)式(死循環(huán)函數(shù))
// 沒有返回值
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”。

// 哪怕沒有顯示的return 也會(huì)報(bào)錯(cuò), 因?yàn)楹瘮?shù)有默認(rèn)返回undefined
function error():never {
  new Error('something failed')
}
// 返回“never”的函數(shù)不能具有可訪問的終結(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類型的屬性是合法的
    // 任意類型有可能是對象類型
    a.b()
}


function fn2(a:unknown){
    // unknown 未知類型, 不確定它是什么值
    a.b()
    // 報(bào)錯(cuò):類型“unknown”上不存在屬性“b”。
}


2.11 枚舉類型

枚舉類型是TypeScript添加到JavaScript的一項(xiàng)功能, 它允許描述一個(gè)值, 該值可能是一組可能的命名常量之一.

與大多數(shù)TypeScript功能不同,這不是對JavaScript的類型級添加, 而是添加到語言和運(yùn)行時(shí)的東西.

詳細(xì)內(nèi)容稍后章節(jié)介紹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容