網站首頁 編程語言 正文
TypeScript 介紹
- TypeScript 是 JavaScript 的超集,提供了 JavaScript 的所有功能,并提供了可選的靜態類型、Mixin、類、接口和泛型等特性。
- TypeScript 的目標是通過其類型系統幫助及早發現錯誤并提高 JavaScript 開發效率。
- 通過 TypeScript 編譯器或 Babel 轉碼器轉譯為 JavaScript 代碼,可運行在任何瀏覽器,任何操作系統。
- 任何現有的 JavaScript 程序都可以運行在 TypeScript 環境中,并只對其中的 TypeScript 代碼進行編譯。
- 在完整保留 JavaScript 運行時行為的基礎上,通過引入靜態類型定義來提高代碼的可維護性,減少可能出現的 bug。
- 永遠不會改變 JavaScript 代碼的運行時行為,例如數字除以零等于 Infinity。這意味著,如果將代碼從 JavaScript 遷移到 TypeScript ,即使 TypeScript 認為代碼有類型錯誤,也可以保證以相同的方式運行。
- 對 JavaScript 類型進行了擴展,增加了例如
any
、unknown
、never
、void
。 - 一旦 TypeScript 的編譯器完成了檢查代碼的工作,它就會 擦除 類型以生成最終的“已編譯”代碼。這意味著一旦代碼被編譯,生成的普通 JS 代碼便沒有類型信息。這也意味著 TypeScript 絕不會根據它推斷的類型更改程序的 行為。最重要的是,盡管您可能會在編譯過程中看到類型錯誤,但類型系統自身與程序如何運行無關。
- 在較大型的項目中,可以在單獨的文件 tsconfig.json 中聲明 TypeScript 編譯器的配置,并細化地調整其工作方式、嚴格程度、以及將編譯后的文件存儲在何處。
類型分配
創建變量時,TypeScript 有兩種分配類型的方式:
- 顯式的 - 明確寫出類型。更易于閱讀且更有目的性。
- 隱式的 - 不寫出類型,TypeScript 將根據分配的值“猜測”類型(稱為 infer 類型推導)。分配更短,輸入速度更快,并且經常在開發和測試時使用。
let firstName = "Dylan"; // 推斷為 string 類型 firstName = 33; // 現在賦值為 number 類型,報錯
TypeScript 不能正確地推斷出變量的類型時,將設置類型為 any(禁用類型檢查的類型)。
// json 為隱式 any 類型,因為 JSON.parse 不知道它返回什么類型的數據 let json = JSON.parse("55"); console.log(typeof json); // number json = '1'; console.log(typeof json); // string
類型推導
- 在沒有顯式類型注釋時使用類型推斷來提供類型信息。例如,下面隱式聲明變量:
let x = 3;
變量的類型 x
將被推斷為 number
,這種推斷發生在初始化變量和成員、設置參數默認值和確定函數返回類型時。
- 當從多個表達式進行類型推斷時,這些表達式的類型用于計算“最佳通用類型”。
let x = [0, 1, ''];
要推斷上例中 x
的類型,我們必須考慮每個數組元素的類型。在這里,我們為數組類型提供了兩種選擇:number
和 string
,可以看到提示推導為 let x: (number | string)[]
。
- 在某些情況下類型共享公共結構,但沒有一種類型是所有候選類型的超類型。
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()];
當沒有找到“最佳通用類型”時,得到的推斷將是聯合數組類型,可以看到提示推導為 let zoo: (Rhino | Elephant | Snake)[]
。
理想情況下,我們可能希望 zoo
被推斷為 Animal[]
,但是因為數組中沒有嚴格意義上的 Animal
類型的對象,所以我們沒有對數組元素類型進行推斷。為了糾正這一點,當沒有一個類型是所有其他候選類型的超級類型時,就明確地提供類型。
let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];
- 當表達式的類型由其所在位置暗示時,就會出現上下文類型化。例如:
window.onmousedown = function (mouseEvent) { console.log(mouseEvent.button); console.log(mouseEvent.kangaroo); };
在這里,TypeScript 類型檢查器通過 Window.onmousedown
事件能夠推斷出 mouseEvent
參數的類型,該參數確實包含 button
屬性,但不包含 kangaroo
屬性。可以看到報錯提示:Property 'kangaroo' does not exist on type 'MouseEvent'.
。TypeScript 足夠聰明,它也可以在其他上下文中推斷類型:
window.onscroll = function (uiEvent) { console.log(uiEvent.button); };
TypeScript 知道 Window.onscroll
事件中參數 uiEvent
是一個 UIEvent
,而不是像前面示例那樣的 MouseEvent
。UIEvent
對象不包含 button
屬性,因此會拋出錯誤 Property 'button' does not exist on type 'Event'.
。
如果此函數不在上下文類型位置,則函數的參數將隱式具有類型 any
,并且不會發出錯誤(除非使用 noImplicitAny
配置):
// @noImplicitAny: false const handler = function (uiEvent) { console.log(uiEvent.button); // <- OK };
我們還可以顯式地為函數的參數提供類型信息以覆蓋任何上下文類型:
window.onscroll = function (uiEvent: any) { console.log(uiEvent.button); // 不報錯,打印undefined,因為UIEvent對象不包含button屬性 };
上下文類型化適用于許多情況。常見情況包括函數調用的參數、賦值的右側、類型斷言、對象和數組文字的成員以及返回語句。上下文類型也會充當“最佳通用類型”中的候選類型。例如:
function createZoo(): Animal[] { return [new Rhino(), new Elephant(), new Snake()]; }
在此示例中,“最佳通用類型”將從以下四個類型中選擇:Animal
、Rhino
、Elephant
和 Snake
。最終,通過“最佳通用類型”算法為 Animal
。
數組
TypeScript 具有定義數組的特定語法。
- 在元素類型后面加上
[]
。
const arr: number[] = [1, 2];
- 使用數組泛型。
const arr2: Array<number> = [1, 2];
-
readonly
關鍵字可以防止數組內容被更改。
const arr: readonly number[] = [1, 2]; // arr.push(3); // Property 'push' does not exist on type 'readonly number[]'.
- 如果數組有值,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'
元組
數組中元素的數據類型都一般是相同的(any[]
類型的數組可以不同),如果存儲的元素數據類型不同,則需要使用元組。
- 如果添加未定義的類型,會拋出錯誤;如果賦值時類型相同,順序不同,同樣會拋出錯誤。
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
關鍵字可以防止元組內容被更改。
let y: readonly [string, number] = ['hi', 1]; // y.push(undefined); // Property 'push' does not exist on type 'readonly [string, number]'.
- “命名元組”允許為我們的索引值所代表的內容提供更多上下文。
const graph: [x: number, y: number] = [55.2, 41.3]; const [a, b] = graph;
object
- TypeScript 具有定義對象的特定語法。
const car: { type: string, model: string, year: number } = { type: "Toyota", model: "Corolla", year: 2009 };
對象類型可以單獨寫,也可以作為類型別名和接口重用。
- TypeScript 可以根據屬性的值推斷屬性的類型。
const car = { type: "Toyota", }; car.type = "Ford"; // car.type = 2; // Type 'number' is not assignable to type 'string'.
- 可選屬性是不必在對象定義中定義的屬性。
const car: { type: string, mileage?: number } = { // no error type: "Toyota" }; car.mileage = 2000;
- 索引簽名可用于沒有定義屬性列表的對象。
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>
實現。
- Typescript 中的對象必須是特定類型的實例。
const sites = { site1: "Runoob", site2: "Google", }; sites.sayHello = function() { console.log("hello " + sites.site1); }; sites.sayHello();
上面示例在對象上面沒有對應的 sayHello
類型定義,將不能進行屬性賦值,會出現編譯錯誤,:Property 'sayHello' does not exist on type '{ site1: string; site2: string; }'.
,所以必須在對象上面定義類型模板。
const sites = { site1: "Runoob", site2: "Google", sayHello: function() {} };
null 和 undefined
默認情況下 null
和 undefined
處理是禁用的,可以通過在 tsconfig.json 中設置 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'
- 空值合并
??
是另一個 JavaScript 特性,它也可以很好地與 TypeScript 的空值處理配合使用。
function printMileage(mileage: number | null | undefined) { console.log(`Mileage: ${mileage ?? 'Not Available'}`); } printMileage(null); // 'Mileage: Not Available' printMileage(0); // 'Mileage: 0'
- TypeScript 還有一種特殊的空值斷言語法,可以在不進行任何顯式檢查的情況下從類型中刪除
null
和undefined
。在任何表達式之后寫!
,表明該值不是null
或undefined
。
function liveDangerously(x?: number | null) { // No error console.log(x!.toFixed()); }
就像其他類型斷言一樣,這不會改變代碼的運行時行為,所以只有當您知道該值不能為 null
或 undefined
時使用 !
。
- 即使啟用了
strictNullChecks
,默認情況下 TypeScript 也會假定數組訪問永遠不會返回undefined
(除非undefined
是數組類型的一部分)。通過配置noUncheckedIndexedAccess
可用于更改此行為。
let array: number[] = [1, 2, 3]; let value = array[0]; // `number | undefined` "noUncheckedIndexedAccess": true
特殊類型
TypeScript 具有可能不引用任何特定類型數據的特殊類型。
any
any
是一種禁用類型檢查并有效地允許使用所有類型的類型。any
類型是一種消除錯誤的有用方法,因為它禁用了類型檢查,但 TypeScript 將無法提供類型安全,并且依賴類型數據的工具(例如自動完成)將無法工作。所以,我們應盡量避免使用它。
以下三種情況可以使用 any
類型。
- 變量的值會動態改變時,比如來自用戶的輸入。
let x: any = 1; // 數字類型 x = 'I am who I am'; // 字符串類型 x = false; // 布爾類型
- 改寫現有代碼時,任意值允許在編譯時可選擇地包含或移除類型檢查。
let v: any = true; v = "string"; // 沒有錯誤 v.ifItExists(); // ifItExists 方法在運行時可能不存在而報錯,但這里并不會檢查 console.log(Math.round(v)); // 沒有錯誤
- 定義存儲各種類型數據的數組。
const arrayList: any[] = [1, false, 'fine']; arrayList[1] = 100;
unknown
unknown
類型表示任何值,類似于 any
類型,但更安全,因為用未知值做任何事情都是不合法的。由于 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'
- 函數返回值類型為
unknown
時要有return
語句。
function f(): unknown {} // A function whose declared type is neither 'void' nor 'any' must return a value
- 當不知道輸入的數據類型時,最好使用
unknown
。要稍后添加類型,需要強制轉換它。
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
代表從不會出現的值,在函數中它通常表現為拋出異常或無法執行到終止點(例如無限循環)。never
很少單獨使用,它的主要用途是在高級泛型中。
function error(message: string): never { throw new Error(message); } function loop(): never { while (true) {} }
void
表示函數沒有任何返回語句,或者不從這些返回語句返回任何顯式值。在 JavaScript 中,不返回任何值的函數將隱式返回值 undefined
。但是,void
和返回 undefined
在 TypeScript 中不是一回事。
function hello(): void { console.log("Hello"); return true; // Type 'boolean' is not assignable to type 'void'. } hello();
函數類型 type vf = () => void
在實現時可以返回任何其他值,以下類型的實現是有效的:
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
原文鏈接:https://juejin.cn/post/7193636842750050360
相關推薦
- 2022-09-16 利用Python統計Jira數據并可視化_python
- 2023-03-13 React?createRef循環動態賦值ref問題_React
- 2022-12-15 C++進程鏈接工具之通信器詳解_C 語言
- 2022-05-05 R語言因子類型的實現_R語言
- 2023-04-08 C#獲取時間戳的方法及時間戳轉換問題_C#教程
- 2023-01-13 python中的txt文件轉換為XML_python
- 2023-04-01 Python關于維卷積的理解_python
- 2022-06-24 python學習之讀取配置文件_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支