TypeScript 初學(xué)者快速入門指南 2024 版
共 9322字,需瀏覽 19分鐘
·
2024-05-21 08:50
大廠技術(shù) 高級前端 Node進(jìn)階
點擊上方 程序員成長指北,關(guān)注公眾號
回復(fù)1,加入高級Node交流群
在這個數(shù)字化的時代,Web開發(fā)技術(shù)正在以驚人的速度進(jìn)步。如果你是一個前端、后端甚至是全棧開發(fā)者,那么跟上這些技術(shù)的步伐絕對是必須的。今天,我要介紹的是一個讓JavaScript煥發(fā)新生的神奇工具——TypeScript。通過這篇文章,我將帶你快速了解TypeScript的基礎(chǔ)概念,不僅適合初學(xué)者,還希望能為有經(jīng)驗的開發(fā)者提供一些有趣的視角。
1) TypeScript簡介
想象一下,如果JavaScript穿上了一件“類型”的盔甲,那么這就是TypeScript。TypeScript擴(kuò)展了JavaScript,通過添加靜態(tài)類型,不僅能在編譯時捕獲錯誤,還能提升代碼的組織性和可維護(hù)性。例如,一個簡單的問候函數(shù)如下所示:
function greet(name: string) {
return `Hello, ${name}!`;
}
console.log(greet("Alice"));
這個例子演示了如何指定參數(shù)name的類型為string,幫助確保使用該函數(shù)時的數(shù)據(jù)類型正確性。
小技巧:利用TypeScript定義變量、函數(shù)等的類型,可以大大提高代碼的可靠性。
最佳用例:對于需要類型安全的大型應(yīng)用來說,TypeScript是理想選擇。
2) 基礎(chǔ)類型
TypeScript支持多種基礎(chǔ)類型,包括數(shù)字(number)、字符串(string)、布爾值(boolean)、數(shù)組等,讓變量的定義更加清晰明確:
let age: number = 25;
let name: string = "Bob";
let isStudent: boolean = true;
let numbers: number[] = [1, 2, 3, 4, 5];
小技巧:盡可能利用類型推斷,讓TypeScript自動確定變量的類型。
最佳用例:適用于代碼中需要定義簡單數(shù)據(jù)類型的場景。
3) 接口(Interfaces)
接口是TypeScript定義對象結(jié)構(gòu)的一種強(qiáng)大方式,它能確保對象遵循特定的格式:
interface Person {
name: string;
age: number;
}
function greet(person: Person) {
return `Hello, ${person.name}!`;
}
小技巧:接口可以幫助你在對象間強(qiáng)制實現(xiàn)一致的結(jié)構(gòu)。
最佳用例:在應(yīng)用程序中定義數(shù)據(jù)契約時非常有用。
4) 類(Classes)
TypeScript的類讓你能夠利用面向?qū)ο缶幊痰母拍?,如繼承和封裝,以一種結(jié)構(gòu)化的方式來模擬現(xiàn)實世界的實體:
class Animal {
constructor(public name: string) {}
move(distance: number) {
console.log(`${this.name} moved ${distance} meters.`);
}
}
小技巧:利用public、private和protected等訪問修飾符來實現(xiàn)更好的封裝。
最佳用例:非常適合在代碼中建?,F(xiàn)實世界的實體。
5) 泛型(Generics)
泛型提供了一種方式,使你能夠創(chuàng)建可以適用于多種數(shù)據(jù)類型的可重用組件:
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("hello");
小技巧:當(dāng)你希望一個函數(shù)或類能夠與任何數(shù)據(jù)類型一起工作時,使用泛型。
最佳用例:創(chuàng)建靈活且可重用的代碼時非常有幫助。
6) 枚舉(Enums)
枚舉允許你定義一組命名的常量,通過這種方式可以使代碼更加清晰易讀:
enum Direction {
Up,
Down,
Left,
Right
}
let heading: Direction = Direction.Up;
小技巧:枚舉通過為數(shù)字值賦予友好的名稱,幫助使你的代碼更易于閱讀和理解。
最佳用例:當(dāng)你有一組相關(guān)的常量時非常有用,如方向、狀態(tài)碼等。
7) 類型斷言(Type Assertion)
類型斷言允許你在TypeScript無法推斷變量類型時,明確告訴編譯器變量的類型:
let input: any = "hello";
let length: number = (input as string).length;
小技巧:當(dāng)你對某個值的了解超過TypeScript時,使用類型斷言。
最佳用例:在處理外部數(shù)據(jù)源的數(shù)據(jù)時特別有幫助。
8) 裝飾器(Decorators)
裝飾器是一種特殊的聲明,可以附加到類、方法、訪問器、屬性或參數(shù)上:
function log(target: any, key: string) {
console.log(`Method ${key} called`);
}
class Example {
@log
someMethod() {
// 方法實現(xiàn)
}
}
小技巧:在Angular等框架中,裝飾器廣泛用于元數(shù)據(jù)反射。
最佳用例:對于向類及其成員添加元數(shù)據(jù)非常有用。
9) 模塊(Modules)
TypeScript中的模塊幫助將代碼組織成可重用的單元:
// math.ts
export function add(a: number, b: number): number {
return a + b;
}
// app.ts
import { add } from './math';
console.log(add(2, 3)); // 輸出: 5
小技巧:利用模塊保持你的代碼庫整潔和可維護(hù)。
最佳用例:對于構(gòu)建大型應(yīng)用結(jié)構(gòu)至關(guān)重要。
10) 命名空間(Namespaces)
命名空間允許你通過分組邏輯相關(guān)的對象來組織代碼:
namespace Geometry {
export class Circle {
// Circle類的實現(xiàn)
}
}
let circle = new Geometry.Circle();
在現(xiàn)代JavaScript和TypeScript開發(fā)中,模塊已經(jīng)成為組織代碼的首選方式。然而,在某些特定場景下,命名空間仍然非常有用,特別是在將現(xiàn)有的大型代碼庫遷移到TypeScript時。
11) 類型推斷(Type Inference)
TypeScript的類型推斷能力意味著即使在未顯式指定類型的情況下,編譯器也能自動確定變量的類型:
let num = 10; // TypeScript推斷出類型為number
小技巧:TypeScript的類型推斷能節(jié)省時間,使代碼更加清晰。
最佳用例:編寫簡潔的代碼時,不犧牲類型安全。
12) 類型守衛(wèi)(Type Guards)
類型守衛(wèi)允許你在條件塊內(nèi)縮小變量的類型范圍:
function isNumber(x: any): x is number {
return typeof x === "number";
}
if (isNumber(value)) {
// 在這個塊里,TypeScript知道'value'是一個數(shù)字
}
小技巧:類型守衛(wèi)在處理聯(lián)合類型時特別有幫助。
最佳用例:處理復(fù)雜或動態(tài)數(shù)據(jù)類型時非常有用。
13) 聯(lián)合類型(Union Types)
聯(lián)合類型允許一個變量具有多種類型:
let result: number | string;
result = 10; // 有效
result = "error"; // 也有效
小技巧:使用聯(lián)合類型來處理變量的不同場景。
最佳用例:適用于表示多樣化的數(shù)據(jù)類型。
14) 交叉類型(Intersection Types)
交叉類型允許將多種類型組合成一個類型:
type A = { a: number };
type B = { b: string };
type C = A & B; // C同時擁有number類型的屬性和string類型的屬性
小技巧:交叉類型用于組合不同類型,處理復(fù)雜場景。
最佳用例:創(chuàng)建復(fù)雜的數(shù)據(jù)結(jié)構(gòu)時非常有幫助。
15) 類型別名(Type Aliases)
類型別名讓你為任何數(shù)據(jù)類型創(chuàng)建一個名稱:
type Age = number;
let userAge: Age = 25;
小技巧:使用類型別名為復(fù)雜的類型提供描述性名稱。
最佳用例:提高代碼的可讀性和可維護(hù)性。
16) 三斜線指令(Triple-Slash Directives)
三斜線指令是包含單個XML標(biāo)簽的單行注釋,常用于聲明文件間的依賴關(guān)系:
/// <reference path="myModule.d.ts" />
小技巧:三斜線指令通常用于聲明文件之間的依賴,有助于模塊和聲明文件的工作。
最佳用例:在處理模塊和聲明文件時非常有用。
17) 對JavaScript文件的類型檢查
TypeScript不僅可以用來編寫TypeScript代碼,還可以用于檢查和類型檢查JavaScript文件:
// @ts-check
let num: number = "not a number"; // TypeScript會拋出類型錯誤
小技巧:對JavaScript文件進(jìn)行類型檢查可以捕獲bug并提升代碼質(zhì)量。
最佳用例:對于逐漸將JavaScript代碼庫遷移到TypeScript的項目非常有用。
18) 解構(gòu)對象的類型推斷
TypeScript能夠為解構(gòu)的對象推斷出類型:
let person = { name: "Alice", age: 30 };
let { name, age } = person; // TypeScript推斷出'name'和'age'的類型
小技巧:解構(gòu)對象的類型推斷能節(jié)省時間,減少冗余。
最佳用例:在處理復(fù)雜的數(shù)據(jù)結(jié)構(gòu)時非常有幫助。
19) 條件類型(Conditional Types)
TypeScript中的條件類型允許你創(chuàng)建依賴于其他類型的類型:
type NonNullable<T> = T extends null | undefined ? never : T;
type StringOrNumber = string | number;
type NonNullableStringOrNumber = NonNullable<StringOrNumber>; // 結(jié)果: string | number
小技巧:條件類型對于創(chuàng)建靈活和條件依賴的類型定義非常強(qiáng)大。
最佳用例:對于創(chuàng)建依賴于條件的泛型類型非常有用。
20) 映射類型(Mapped Types)
TypeScript的映射類型允許你從現(xiàn)有類型創(chuàng)建新類型:
type Flags = {
option1: boolean;
option2: boolean;
};
type NullableFlags = { [K in keyof Flags]: Flags[K] | null }; // 結(jié)果: { option1: boolean | null, option2: boolean | null }
小技巧:映射類型用于將現(xiàn)有類型轉(zhuǎn)換為新類型。
最佳用例:在創(chuàng)建現(xiàn)有類型的變體時非常有幫助。
21) 聲明合并(Declaration Merging)
在TypeScript中,聲明合并允許為同一個實體合并多個聲明:
interface User {
name: string;
}
interface User {
age: number;
}
let newUser: User = { name: "Alice", age: 30 };
小技巧:聲明合并對于擴(kuò)展現(xiàn)有類型非常有用,且不需要直接修改它們。
最佳用例:對第三方庫添加功能時特別有幫助。
22) 類型守衛(wèi)與類(Type Guards with Classes)
類型守衛(wèi)也可以用于類,以縮小實例的類型范圍:
class Animal {
move() {
console.log("Moving...");
}
}
class Dog extends Animal {
bark() {
console.log("Woof!");
}
}
function isDog(animal: Animal): animal is Dog {
return (animal as Dog).bark !== undefined;
}
小技巧:對于處理多態(tài)性行為,使用類的類型守衛(wèi)非常有用。
最佳用例:在處理繼承和多態(tài)性時非常有效。
23) 元組類型(Tuple Types)
TypeScript的元組類型允許表達(dá)一個數(shù)組,其中固定數(shù)量的元素的類型是已知的:
let coordinates: [number, number] = [10, 20];
小技巧:在處理已知元素類型的固定長度數(shù)組時使用元組類型。
最佳用例:用于表示結(jié)構(gòu)化數(shù)據(jù),如坐標(biāo)、RGB值等。
24) 索引簽名(Index Signatures)
索引簽名允許定義對象如何被索引:
interface StringArray {
[index: number]: string;
}
let myArray: StringArray = ["a", "b", "c"];
小技巧:索引簽名用于處理表現(xiàn)得像數(shù)組的對象。
最佳用例:在處理動態(tài)數(shù)據(jù)結(jié)構(gòu)時非常有幫助。
25) 使用typeof和instanceof的類型守衛(wèi)(Type Guards with typeof and instanceof)
可以使用typeof和instanceof操作符創(chuàng)建類型守衛(wèi):
function logValue(value: string | number) {
if (typeof value === "string") {
console.log(value.toUpperCase());
} else if (value instanceof Number) {
console.log(value.valueOf());
}
}
小技巧:使用typeof來檢查原始類型,使用instanceof來檢查類的實例。
最佳用例:在條件塊中檢查特定類型時非常有用。
26) 遞歸類型(Recursive Types)
TypeScript支持定義遞歸類型,即一個類型可以引用它自身:
interface TreeNode {
value: string;
children: TreeNode[];
}
小技巧:遞歸類型對于表示層級數(shù)據(jù)結(jié)構(gòu)非常有用。
最佳用例:非常適合模擬樹形數(shù)據(jù),如文件系統(tǒng)的目錄結(jié)構(gòu)。
27) 字符串字面量類型(String Literal Types)
字符串字面量類型允許定義一個類型,它只能有特定的字符串值:
type Direction = "up" | "down" | "left" | "right";
let move: Direction = "up";
小技巧:字符串字面量類型有助于創(chuàng)建具體和簡潔的類型定義。
最佳用例:用于表示一組固定的字符串值,如命令、方向等。
28) 命名空間合并(Namespace Merging)
命名空間合并允許在多個文件中擴(kuò)展現(xiàn)有的命名空間:
// math.ts
namespace Math {
export function subtract(a: number, b: number): number {
return a - b;
}
}
// extendedMath.ts
namespace Math {
export function multiply(a: number, b: number): number {
return a * b;
}
}
小技巧:命名空間合并有用于為現(xiàn)有命名空間添加功能。
最佳用例:幫助在多個文件中模塊化代碼。
29) 類型謂詞(Type Predicates)
類型謂詞是返回類型謂詞的函數(shù),用于在條件塊內(nèi)縮小類型范圍:
function isString(value: any): value is string {
return typeof value === "string";
}
if (isString(input)) {
console.log(input.toUpperCase());
}
小技巧:類型謂詞對于創(chuàng)建可重用的類型縮小函數(shù)非常有用。
最佳用例:處理復(fù)雜的類型檢查時非常有效。
30) 類型推斷和嚴(yán)格模式(Inference and Strict Mode)
TypeScript的嚴(yán)格模式啟用額外的類型檢查選項,以捕獲更多錯誤:
// @ts-check
let num: number = "not a number"; // 在嚴(yán)格模式下,TypeScript會拋出類型錯誤
小技巧:嚴(yán)格模式可以幫助捕獲更多潛在的類型錯誤,提升代碼質(zhì)量。
最佳用例:對于希望增強(qiáng)類型安全和避免潛在錯誤的項目非常有用。
31) 使用in操作符的類型守衛(wèi)
可以使用in操作符創(chuàng)建類型守衛(wèi),以檢查對象中是否存在某個屬性:
function hasName(obj: any): obj is { name: string } {
return "name" in obj;
}
if (hasName(user)) {
console.log(user.name);
}
小技巧:in操作符對于動態(tài)檢查屬性存在性非常有用。
最佳用例:在類型安全的方式下檢查對象屬性時非常有幫助。
32) 數(shù)組的類型推斷
TypeScript能夠基于分配給它們的元素推斷數(shù)組的類型:
let numbers = [1, 2, 3]; // TypeScript推斷'numbers'為number[]
小技巧:數(shù)組的類型推斷可以簡化代碼并提高可讀性。
最佳用例:用于處理已知元素的數(shù)組。
33) Promise和異步/等待(Async/Await)
TypeScript支持Promise和async/await語法,用于處理異步操作:
function fetchData(): Promise<string> {
return new Promise(resolve => {
setTimeout(() => {
resolve("Data fetched!");
}, 2000);
});
}
async function fetchDataAsync() {
const data = await fetchData();
console.log(data);
}
小技巧:Promise和async/await對于以同步方式處理異步代碼至關(guān)重要。
最佳用例:在可讀方式管理異步操作時非常有效。
34) 泛型約束(Generics Constraints)
泛型約束允許限制可以用于泛型類型參數(shù)的類型:
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
小技巧:泛型約束確保了類型安全,并向TypeScript提供了更具體的信息。
最佳用例:在受控方式下處理泛型類型時非常有用。
35) 默認(rèn)值的類型推斷
TypeScript可以基于變量的默認(rèn)值推斷類型:
let message = "Hello, World!"; // TypeScript推斷'message'為string
小技巧:默認(rèn)值的類型推斷對于初始化變量而不顯式指定類型非常方便。
最佳用例:用于減少代碼冗長,允許TypeScript基于初始值推斷類型。
結(jié)束
在這次的探索旅程中,我們一起深入了解了TypeScript的強(qiáng)大特性,從基礎(chǔ)的類型系統(tǒng)到復(fù)雜的高級技巧,TypeScript無疑為我們打開了編程世界的新視野。無論是對于初學(xué)者還是資深開發(fā)者,TypeScript都提供了強(qiáng)大的工具和機(jī)制,讓我們可以以更安全、更高效的方式來構(gòu)建應(yīng)用程序。
通過這系列文章,我們希望你能夠感受到TypeScript的魅力,以及它如何幫助你提升代碼的質(zhì)量和可維護(hù)性。記住,學(xué)習(xí)一門新技術(shù)總是充滿挑戰(zhàn),但隨著你不斷探索和實踐,這些挑戰(zhàn)最終將轉(zhuǎn)化為你寶貴的技能和經(jīng)驗。
Node 社群
我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學(xué)習(xí)感興趣的話(后續(xù)有計劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。
“分享、點贊、在看” 支持一下
