TypeScript 基本數(shù)據(jù)類型實(shí)例詳解
TypeScript 介紹
- TypeScript 是 JavaScript 的超集,提供了 JavaScript 的所有功能,并提供了可選的靜態(tài)類型、Mixin、類、接口和泛型等特性。
- TypeScript 的目標(biāo)是通過其類型系統(tǒng)幫助及早發(fā)現(xiàn)錯(cuò)誤并提高 JavaScript 開發(fā)效率。
- 通過 TypeScript 編譯器或 Babel 轉(zhuǎn)碼器轉(zhuǎn)譯為 JavaScript 代碼,可運(yùn)行在任何瀏覽器,任何操作系統(tǒng)。
- 任何現(xiàn)有的 JavaScript 程序都可以運(yùn)行在 TypeScript 環(huán)境中,并只對(duì)其中的 TypeScript 代碼進(jìn)行編譯。
- 在完整保留 JavaScript 運(yùn)行時(shí)行為的基礎(chǔ)上,通過引入靜態(tài)類型定義來提高代碼的可維護(hù)性,減少可能出現(xiàn)的 bug。
- 永遠(yuǎn)不會(huì)改變 JavaScript 代碼的運(yùn)行時(shí)行為,例如數(shù)字除以零等于 Infinity。這意味著,如果將代碼從 JavaScript 遷移到 TypeScript ,即使 TypeScript 認(rèn)為代碼有類型錯(cuò)誤,也可以保證以相同的方式運(yùn)行。
- 對(duì) JavaScript 類型進(jìn)行了擴(kuò)展,增加了例如
any
、unknown
、never
、void
。 - 一旦 TypeScript 的編譯器完成了檢查代碼的工作,它就會(huì) 擦除 類型以生成最終的“已編譯”代碼。這意味著一旦代碼被編譯,生成的普通 JS 代碼便沒有類型信息。這也意味著 TypeScript 絕不會(huì)根據(jù)它推斷的類型更改程序的 行為。最重要的是,盡管您可能會(huì)在編譯過程中看到類型錯(cuò)誤,但類型系統(tǒng)自身與程序如何運(yùn)行無關(guān)。
- 在較大型的項(xiàng)目中,可以在單獨(dú)的文件 tsconfig.json 中聲明 TypeScript 編譯器的配置,并細(xì)化地調(diào)整其工作方式、嚴(yán)格程度、以及將編譯后的文件存儲(chǔ)在何處。
類型分配
創(chuàng)建變量時(shí),TypeScript 有兩種分配類型的方式:
- 顯式的 - 明確寫出類型。更易于閱讀且更有目的性。
- 隱式的 - 不寫出類型,TypeScript 將根據(jù)分配的值“猜測”類型(稱為 infer 類型推導(dǎo))。分配更短,輸入速度更快,并且經(jīng)常在開發(fā)和測試時(shí)使用。
let firstName = "Dylan"; // 推斷為 string 類型 firstName = 33; // 現(xiàn)在賦值為 number 類型,報(bào)錯(cuò)
TypeScript 不能正確地推斷出變量的類型時(shí),將設(shè)置類型為 any(禁用類型檢查的類型)。
// json 為隱式 any 類型,因?yàn)?JSON.parse 不知道它返回什么類型的數(shù)據(jù) let json = JSON.parse("55"); console.log(typeof json); // number json = '1'; console.log(typeof json); // string
類型推導(dǎo)
- 在沒有顯式類型注釋時(shí)使用類型推斷來提供類型信息。例如,下面隱式聲明變量:
let x = 3;
變量的類型 x
將被推斷為 number
,這種推斷發(fā)生在初始化變量和成員、設(shè)置參數(shù)默認(rèn)值和確定函數(shù)返回類型時(shí)。
- 當(dāng)從多個(gè)表達(dá)式進(jìn)行類型推斷時(shí),這些表達(dá)式的類型用于計(jì)算“最佳通用類型”。
let x = [0, 1, ''];
要推斷上例中 x
的類型,我們必須考慮每個(gè)數(shù)組元素的類型。在這里,我們?yōu)閿?shù)組類型提供了兩種選擇:number
和 string
,可以看到提示推導(dǎo)為 let x: (number | string)[]
。
- 在某些情況下類型共享公共結(jié)構(gòu),但沒有一種類型是所有候選類型的超類型。
class Animal {} class Rhino extends Animal { hasHorn: true; } class Elephant extends Animal { hasTrunk: true; } class Snake extends Animal { hasLegs: false; } let zoo = [new Rhino(), new Elephant(), new Snake()];
當(dāng)沒有找到“最佳通用類型”時(shí),得到的推斷將是聯(lián)合數(shù)組類型,可以看到提示推導(dǎo)為 let zoo: (Rhino | Elephant | Snake)[]
。
理想情況下,我們可能希望 zoo
被推斷為 Animal[]
,但是因?yàn)閿?shù)組中沒有嚴(yán)格意義上的 Animal
類型的對(duì)象,所以我們沒有對(duì)數(shù)組元素類型進(jìn)行推斷。為了糾正這一點(diǎn),當(dāng)沒有一個(gè)類型是所有其他候選類型的超級(jí)類型時(shí),就明確地提供類型。
let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];
- 當(dāng)表達(dá)式的類型由其所在位置暗示時(shí),就會(huì)出現(xiàn)上下文類型化。例如:
window.onmousedown = function (mouseEvent) { console.log(mouseEvent.button); console.log(mouseEvent.kangaroo); };
在這里,TypeScript 類型檢查器通過 Window.onmousedown
事件能夠推斷出 mouseEvent
參數(shù)的類型,該參數(shù)確實(shí)包含 button
屬性,但不包含 kangaroo
屬性??梢钥吹綀?bào)錯(cuò)提示:Property 'kangaroo' does not exist on type 'MouseEvent'.
。TypeScript 足夠聰明,它也可以在其他上下文中推斷類型:
window.onscroll = function (uiEvent) { console.log(uiEvent.button); };
TypeScript 知道 Window.onscroll
事件中參數(shù) uiEvent
是一個(gè) UIEvent
,而不是像前面示例那樣的 MouseEvent
。UIEvent
對(duì)象不包含 button
屬性,因此會(huì)拋出錯(cuò)誤 Property 'button' does not exist on type 'Event'.
。
如果此函數(shù)不在上下文類型位置,則函數(shù)的參數(shù)將隱式具有類型 any
,并且不會(huì)發(fā)出錯(cuò)誤(除非使用 noImplicitAny
配置):
// @noImplicitAny: false const handler = function (uiEvent) { console.log(uiEvent.button); // <- OK };
我們還可以顯式地為函數(shù)的參數(shù)提供類型信息以覆蓋任何上下文類型:
window.onscroll = function (uiEvent: any) { console.log(uiEvent.button); // 不報(bào)錯(cuò),打印undefined,因?yàn)閁IEvent對(duì)象不包含button屬性 };
上下文類型化適用于許多情況。常見情況包括函數(shù)調(diào)用的參數(shù)、賦值的右側(cè)、類型斷言、對(duì)象和數(shù)組文字的成員以及返回語句。上下文類型也會(huì)充當(dāng)“最佳通用類型”中的候選類型。例如:
function createZoo(): Animal[] { return [new Rhino(), new Elephant(), new Snake()]; }
在此示例中,“最佳通用類型”將從以下四個(gè)類型中選擇:Animal
、Rhino
、Elephant
和 Snake
。最終,通過“最佳通用類型”算法為 Animal
。
數(shù)組
TypeScript 具有定義數(shù)組的特定語法。
- 在元素類型后面加上
[]
。
const arr: number[] = [1, 2];
- 使用數(shù)組泛型。
const arr2: Array<number> = [1, 2];
readonly
關(guān)鍵字可以防止數(shù)組內(nèi)容被更改。
const arr: readonly number[] = [1, 2]; // arr.push(3); // Property 'push' does not exist on type 'readonly number[]'.
- 如果數(shù)組有值,TypeScript 可以推斷它的類型。
const numbers = [1, 2, 3]; // 推斷為類型 number[] numbers.push(4); // OK // numbers.push("2"); // Argument of type 'string' is not assignable to parameter of type 'number'
元組
數(shù)組中元素的數(shù)據(jù)類型都一般是相同的(any[]
類型的數(shù)組可以不同),如果存儲(chǔ)的元素?cái)?shù)據(jù)類型不同,則需要使用元組。
- 如果添加未定義的類型,會(huì)拋出錯(cuò)誤;如果賦值時(shí)類型相同,順序不同,同樣會(huì)拋出錯(cuò)誤。
let x: [string, number]; x = ['hi', 1]; // x.push(true); // Argument of type 'boolean' is not assignable to parameter of type 'string | number'. // x = [1, 'hi']; // Type 'number' is not assignable to type 'string'. Type 'string' is not assignable to type 'number'.
readonly
關(guān)鍵字可以防止元組內(nèi)容被更改。
let y: readonly [string, number] = ['hi', 1]; // y.push(undefined); // Property 'push' does not exist on type 'readonly [string, number]'.
- “命名元組”允許為我們的索引值所代表的內(nèi)容提供更多上下文。
const graph: [x: number, y: number] = [55.2, 41.3]; const [a, b] = graph;
object
- TypeScript 具有定義對(duì)象的特定語法。
const car: { type: string, model: string, year: number } = { type: "Toyota", model: "Corolla", year: 2009 };
對(duì)象類型可以單獨(dú)寫,也可以作為類型別名和接口重用。
- TypeScript 可以根據(jù)屬性的值推斷屬性的類型。
const car = { type: "Toyota", }; car.type = "Ford"; // car.type = 2; // Type 'number' is not assignable to type 'string'.
- 可選屬性是不必在對(duì)象定義中定義的屬性。
const car: { type: string, mileage?: number } = { // no error type: "Toyota" }; car.mileage = 2000;
- 索引簽名可用于沒有定義屬性列表的對(duì)象。
const nameAgeMap: { [index: string]: number } = {}; nameAgeMap.Jack = 25; // no error nameAgeMap.Mark = "Fifty"; // Error: Type 'string' is not assignable to type 'number'.
上述索引簽名也可以通過使用工具類型 Record<string, number>
實(shí)現(xiàn)。
- Typescript 中的對(duì)象必須是特定類型的實(shí)例。
const sites = { site1: "Runoob", site2: "Google", }; sites.sayHello = function() { console.log("hello " + sites.site1); }; sites.sayHello();
上面示例在對(duì)象上面沒有對(duì)應(yīng)的 sayHello
類型定義,將不能進(jìn)行屬性賦值,會(huì)出現(xiàn)編譯錯(cuò)誤,:Property 'sayHello' does not exist on type '{ site1: string; site2: string; }'.
,所以必須在對(duì)象上面定義類型模板。
const sites = { site1: "Runoob", site2: "Google", sayHello: function() {} };
null 和 undefined
默認(rèn)情況下 null
和 undefined
處理是禁用的,可以通過在 tsconfig.json 中設(shè)置 strictNullChecks
為 true
來啟用。
null
和undefined
是原始類型,可以像字符串等其他類型一樣使用。
let y: undefined = undefined; console.log(typeof y); let z: null = null; console.log(typeof z);
- 可選鏈
?.
是一種原生 JavaScript 特性,可以很好地與 TypeScript 中的null
和undefined
配合使用。
interface House { sqft: number; yard?: { sqft: number; }; } function printYardSize(house: House) { const yardSize = house.yard?.sqft; if (yardSize === undefined) { console.log('No yard'); } else { console.log(`Yard is ${yardSize} sqft`); } } let home: House = { sqft: 500 }; printYardSize(home); // 'No yard'
- 空值合并
??
是另一個(gè) JavaScript 特性,它也可以很好地與 TypeScript 的空值處理配合使用。
function printMileage(mileage: number | null | undefined) { console.log(`Mileage: ${mileage ?? 'Not Available'}`); } printMileage(null); // 'Mileage: Not Available' printMileage(0); // 'Mileage: 0'
- TypeScript 還有一種特殊的空值斷言語法,可以在不進(jìn)行任何顯式檢查的情況下從類型中刪除
null
和undefined
。在任何表達(dá)式之后寫!
,表明該值不是null
或undefined
。
function liveDangerously(x?: number | null) { // No error console.log(x!.toFixed()); }
就像其他類型斷言一樣,這不會(huì)改變代碼的運(yùn)行時(shí)行為,所以只有當(dāng)您知道該值不能為 null
或 undefined
時(shí)使用 !
。
- 即使啟用了
strictNullChecks
,默認(rèn)情況下 TypeScript 也會(huì)假定數(shù)組訪問永遠(yuǎn)不會(huì)返回undefined
(除非undefined
是數(shù)組類型的一部分)。通過配置noUncheckedIndexedAccess
可用于更改此行為。
let array: number[] = [1, 2, 3]; let value = array[0]; // `number | undefined` "noUncheckedIndexedAccess": true
特殊類型
TypeScript 具有可能不引用任何特定類型數(shù)據(jù)的特殊類型。
any
any
是一種禁用類型檢查并有效地允許使用所有類型的類型。any
類型是一種消除錯(cuò)誤的有用方法,因?yàn)樗昧祟愋蜋z查,但 TypeScript 將無法提供類型安全,并且依賴類型數(shù)據(jù)的工具(例如自動(dòng)完成)將無法工作。所以,我們應(yīng)盡量避免使用它。
以下三種情況可以使用 any
類型。
- 變量的值會(huì)動(dòng)態(tài)改變時(shí),比如來自用戶的輸入。
let x: any = 1; // 數(shù)字類型 x = 'I am who I am'; // 字符串類型 x = false; // 布爾類型
- 改寫現(xiàn)有代碼時(shí),任意值允許在編譯時(shí)可選擇地包含或移除類型檢查。
let v: any = true; v = "string"; // 沒有錯(cuò)誤 v.ifItExists(); // ifItExists 方法在運(yùn)行時(shí)可能不存在而報(bào)錯(cuò),但這里并不會(huì)檢查 console.log(Math.round(v)); // 沒有錯(cuò)誤
- 定義存儲(chǔ)各種類型數(shù)據(jù)的數(shù)組。
const arrayList: any[] = [1, false, 'fine']; arrayList[1] = 100;
unknown
unknown
類型表示任何值,類似于 any
類型,但更安全,因?yàn)橛梦粗底鋈魏问虑槎际遣缓戏ǖ?/strong>。由于 any
違背了類型檢查的初衷,一般不建議使用,尤其在有了 unknown
類型之后。
- 任何類型可以分配給
any
和unknown
,any
可以分配給任何類型,unknown
只能分配給unknown
或者any
。
let a: any; let n: number; let w: unknown = 1; w = "string"; w = a; a = w; n = a; // n = w; // Type 'unknown' is not assignable to type 'number'
- 函數(shù)返回值類型為
unknown
時(shí)要有return
語句。
function f(): unknown {} // A function whose declared type is neither 'void' nor 'any' must return a value
- 當(dāng)不知道輸入的數(shù)據(jù)類型時(shí),最好使用
unknown
。要稍后添加類型,需要強(qiáng)制轉(zhuǎn)換它。
const w = { runANonExistentMethod: () => { console.log("I think therefore I am"); } } as { runANonExistentMethod: () => void }; if(typeof w === 'object' && w !== null) { (w as { runANonExistentMethod: Function }).runANonExistentMethod(); }
never
never
代表從不會(huì)出現(xiàn)的值,在函數(shù)中它通常表現(xiàn)為拋出異?;驘o法執(zhí)行到終止點(diǎn)(例如無限循環(huán))。never
很少單獨(dú)使用,它的主要用途是在高級(jí)泛型中。
function error(message: string): never { throw new Error(message); } function loop(): never { while (true) {} }
void
表示函數(shù)沒有任何返回語句,或者不從這些返回語句返回任何顯式值。在 JavaScript 中,不返回任何值的函數(shù)將隱式返回值 undefined
。但是,void
和返回 undefined
在 TypeScript 中不是一回事。
function hello(): void { console.log("Hello"); return true; // Type 'boolean' is not assignable to type 'void'. } hello();
函數(shù)類型 type vf = () => void
在實(shí)現(xiàn)時(shí)可以返回任何其他值,以下類型的實(shí)現(xiàn)是有效的:
type voidFunc = () => void; const f1: voidFunc = () => { return true; }; const f2: voidFunc = () => true; const f3: voidFunc = function() { return true; }; const v1 = f1(); const v2 = f2(); const v3 = f3(); console.log(v1, v2, v3); // true true true
以上就是TypeScript 基本數(shù)據(jù)類型實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于TypeScript 基本數(shù)據(jù)類型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
TypeScript類型實(shí)現(xiàn)加減乘除詳解
這篇文章主要為大家介紹了TypeScript類型實(shí)現(xiàn)加減乘除示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04rollup?cli開發(fā)全面系統(tǒng)性rollup源碼分析
這篇文章主要為大家介紹了rollup?cli開發(fā)全網(wǎng)系統(tǒng)性rollup源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01移動(dòng)設(shè)備web開發(fā)首選框架:zeptojs介紹
這篇文章主要介紹了移動(dòng)設(shè)備web開發(fā)首選框架:zeptojs介紹,他兼容jquery的API,所以學(xué)起來或用起來并不吃力,需要的朋友可以參考下2015-01-01TypeScript數(shù)組實(shí)現(xiàn)棧與對(duì)象實(shí)現(xiàn)棧的區(qū)別詳解
這篇文章主要為大家介紹了TypeScript數(shù)組實(shí)現(xiàn)棧與對(duì)象實(shí)現(xiàn)棧的區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09