首頁 web前端 js教程 每個開發人員都應該了解的高級打字稿概念

每個開發人員都應該了解的高級打字稿概念

Nov 26, 2024 am 07:18 AM

TypeScript 是一種現代程式語言,由於其附加的型別安全性,通常比 JavaScript 更受青睞。在本文中,我將分享 10 個最重要的 TypeScript 概念,這將有助於提升您的 TypeScript 程式設計技能。準備好了嗎?開始吧。

Top Advanced typescript concepts that Every Developer Should Know

1.泛型:使用泛型我們可以建立可重複使用的類型,這將有助於處理今天和明天的資料。
泛型範例:
我們可能想要 Typescript 中的一個函數將參數作為某種類型,並且我們可能想要傳回相同的類型。

function func<T>(args:T):T{
    return args;
}
登入後複製
登入後複製

2.具有型別約束的泛型:現在讓我們透過定義它只接受字串和整數來限制型別 T:

function func<T extends string | number>(value: T): T {
    return value;
}

const stringValue = func("Hello"); // Works, T is string
const numberValue = func(42);      // Works, T is number

// const booleanValue = func(true); // Error: Type 'boolean' is not assignable to type 'string | number'
登入後複製
登入後複製

3.通用介面:
當您想要為使用各種類型的物件、類別或函數定義契約(形狀)時,介面泛型非常有用。它們允許您定義一個藍圖,該藍圖可以適應不同的資料類型,同時保持結構一致。

// Generic interface with type parameters T and U
interface Repository<T, U> {
    items: T[];           // Array of items of type T
    add(item: T): void;   // Function to add an item of type T
    getById(id: U): T | undefined; // Function to get an item by ID of type U
}

// Implementing the Repository interface for a User entity
interface User {
    id: number;
    name: string;
}

class UserRepository implements Repository<User, number> {
    items: User[] = [];

    add(item: User): void {
        this.items.push(item);
    }

     getById(idOrName: number | string): User | undefined {
        if (typeof idOrName === 'string') {
            // Search by name if idOrName is a string
            console.log('Searching by name:', idOrName);
            return this.items.find(user => user.name === idOrName);
        } else if (typeof idOrName === 'number') {
            // Search by id if idOrName is a number
            console.log('Searching by id:', idOrName);
            return this.items.find(user => user.id === idOrName);
        }
        return undefined; // Return undefined if no match found
    }
}

// Usage
const userRepo = new UserRepository();
userRepo.add({ id: 1, name: "Alice" });
userRepo.add({ id: 2, name: "Bob" });

const user1 = userRepo.getById(1);
const user2 = userRepo.getById("Bob");
console.log(user1); // Output: { id: 1, name: "Alice" }
console.log(user2); // Output: { id: 2, name: "Bob" }

登入後複製
登入後複製

4.泛型類別::當您希望類別中的所有屬性都遵循泛型參數指定的類型時,請使用此選項。這允許靈活性,同時確保類別的每個屬性都與傳遞給類別的類型相符。

interface User {
    id: number;
    name: string;
    age: number;
}

class UserDetails<T extends User> {
    id: T['id'];
    name: T['name'];
    age: T['age'];

    constructor(user: T) {
        this.id = user.id;
        this.name = user.name;
        this.age = user.age;
    }

    // Method to get user details
    getUserDetails(): string {
        return `User: ${this.name}, ID: ${this.id}, Age: ${this.age}`;
    }

    // Method to update user name
    updateName(newName: string): void {
        this.name = newName;
    }

    // Method to update user age
    updateAge(newAge: number): void {
        this.age = newAge;
    }
}

// Using the UserDetails class with a User type
const user: User = { id: 1, name: "Alice", age: 30 };
const userDetails = new UserDetails(user);

console.log(userDetails.getUserDetails());  // Output: "User: Alice, ID: 1, Age: 30"

// Updating user details
userDetails.updateName("Bob");
userDetails.updateAge(35);

console.log(userDetails.getUserDetails());  // Output: "User: Bob, ID: 1, Age: 35"
console.log(new UserDetails("30"));  // Error: "This will throw error" 
登入後複製
登入後複製

5.將型別參數約束為傳遞的型別:有時,我們希望參數型別依賴其他一些傳遞的參數。聽起來很混亂,讓我們看下面的範例。

function getProperty<Type>(obj: Type, key: keyof Type) {
  return obj[key];
}

let x = { a: 1, b: 2, c: 3 };
getProperty(x, "a");  // Valid
getProperty(x, "d");  // Error: Argument of type '"d"' is not assignable to parameter of type '"a" | "b" | "c"'.

登入後複製
登入後複製

6.條件類型:通常,我們希望我們的類型是一種類型或另一種類型。在這種情況下,我們使用條件類型。
一個簡單的例子是:

function func(param:number|boolean){
return param;
}
console.log(func(2)) //Output: 2 will be printed
console.log(func("True")) //Error: boolean cannot be passed as argument

登入後複製
登入後複製

有點複雜的例子:

type HasProperty<T, K extends keyof T> = K extends "age" ? "Has Age" : "Has Name";

interface User {
  name: string;
  age: number;
}

let test1: HasProperty<User, "age">;  // "Has Age"
let test2: HasProperty<User, "name">; // "Has Name"
let test3: HasProperty<User, "email">; // Error: Type '"email"' is not assignable to parameter of type '"age" | "name"'.

登入後複製

6.交集類型:當我們想要將多種類型合併為一個類型時,這些類型非常有用,允許特定類型繼承各種其他類型的屬性和行為。
讓我們來看一個有趣的例子:

// Defining the types for each area of well-being

interface MentalWellness {
  mindfulnessPractice: boolean;
  stressLevel: number; // Scale of 1 to 10
}

interface PhysicalWellness {
  exerciseFrequency: string; // e.g., "daily", "weekly"
  sleepDuration: number; // in hours
}

interface Productivity {
  tasksCompleted: number;
  focusLevel: number; // Scale of 1 to 10
}

// Combining all three areas into a single type using intersection types
type HealthyBody = MentalWellness & PhysicalWellness & Productivity;

// Example of a person with a balanced healthy body
const person: HealthyBody = {
  mindfulnessPractice: true,
  stressLevel: 4,
  exerciseFrequency: "daily",
  sleepDuration: 7,
  tasksCompleted: 15,
  focusLevel: 8
};

// Displaying the information
console.log(person);

登入後複製

7.infer 關鍵字:當我們想要有條件地確定特定類型時,infer 關鍵字很有用,並且當滿足條件時,它允許我們從該類型中提取子類型。
這是一般語法:

type ConditionalType<T> = T extends SomeType ? InferredType : OtherType;
登入後複製

範例:

type ReturnTypeOfPromise<T> = T extends Promise<infer U> ? U : number;

type Result = ReturnTypeOfPromise<Promise<string>>;  // Result is 'string'
type ErrorResult = ReturnTypeOfPromise<number>;      // ErrorResult is 'never'

const result: Result = "Hello";
console.log(typeof result); // Output: 'string'
登入後複製

8.Type Variance:這個概念討論了子類型和父類型如何相互關聯。
它們有兩種類型:
協方差:可以在需要父類型的地方使用子類型。
讓我們來看一個例子:

function func<T>(args:T):T{
    return args;
}
登入後複製
登入後複製

在上面的範例中,Car 繼承了 Vehicle 類別的屬性,因此將其指派給需要超類型的子類型是絕對有效的,因為子類型將具有超類型所具有的所有屬性。
逆變:這與協變相反。我們在子類型應該出現的地方使用超類型。

function func<T extends string | number>(value: T): T {
    return value;
}

const stringValue = func("Hello"); // Works, T is string
const numberValue = func(42);      // Works, T is number

// const booleanValue = func(true); // Error: Type 'boolean' is not assignable to type 'string | number'
登入後複製
登入後複製

使用逆變時,我們需要小心不要存取特定於子類型的屬性或方法,因為這可能會導致錯誤。

9。反思: 這個概念涉及在運行時確定變數的類型。雖然 TypeScript 主要專注於編譯時的類型檢查,但我們仍然可以利用 TypeScript 運算子在執行時檢查類型。
typeof 運算子:我們可以利用 typeof 運算子在執行時尋找變數的型別

// Generic interface with type parameters T and U
interface Repository<T, U> {
    items: T[];           // Array of items of type T
    add(item: T): void;   // Function to add an item of type T
    getById(id: U): T | undefined; // Function to get an item by ID of type U
}

// Implementing the Repository interface for a User entity
interface User {
    id: number;
    name: string;
}

class UserRepository implements Repository<User, number> {
    items: User[] = [];

    add(item: User): void {
        this.items.push(item);
    }

     getById(idOrName: number | string): User | undefined {
        if (typeof idOrName === 'string') {
            // Search by name if idOrName is a string
            console.log('Searching by name:', idOrName);
            return this.items.find(user => user.name === idOrName);
        } else if (typeof idOrName === 'number') {
            // Search by id if idOrName is a number
            console.log('Searching by id:', idOrName);
            return this.items.find(user => user.id === idOrName);
        }
        return undefined; // Return undefined if no match found
    }
}

// Usage
const userRepo = new UserRepository();
userRepo.add({ id: 1, name: "Alice" });
userRepo.add({ id: 2, name: "Bob" });

const user1 = userRepo.getById(1);
const user2 = userRepo.getById("Bob");
console.log(user1); // Output: { id: 1, name: "Alice" }
console.log(user2); // Output: { id: 2, name: "Bob" }

登入後複製
登入後複製

instanceof 運算子:instanceof 運算子可用於檢查物件是否為類別或特定類型的實例。

interface User {
    id: number;
    name: string;
    age: number;
}

class UserDetails<T extends User> {
    id: T['id'];
    name: T['name'];
    age: T['age'];

    constructor(user: T) {
        this.id = user.id;
        this.name = user.name;
        this.age = user.age;
    }

    // Method to get user details
    getUserDetails(): string {
        return `User: ${this.name}, ID: ${this.id}, Age: ${this.age}`;
    }

    // Method to update user name
    updateName(newName: string): void {
        this.name = newName;
    }

    // Method to update user age
    updateAge(newAge: number): void {
        this.age = newAge;
    }
}

// Using the UserDetails class with a User type
const user: User = { id: 1, name: "Alice", age: 30 };
const userDetails = new UserDetails(user);

console.log(userDetails.getUserDetails());  // Output: "User: Alice, ID: 1, Age: 30"

// Updating user details
userDetails.updateName("Bob");
userDetails.updateAge(35);

console.log(userDetails.getUserDetails());  // Output: "User: Bob, ID: 1, Age: 35"
console.log(new UserDetails("30"));  // Error: "This will throw error" 
登入後複製
登入後複製

我們可以使用第三方函式庫在執行時確定類型。

10.依賴注入:依賴注入是一種模式,允許您將程式碼引入元件中,而無需在元件中實際建立或管理它。雖然它看起來像是使用庫,但它有所不同,因為您不需要透過 CDN 或 API 安裝或匯入它。

乍一看,它似乎也類似於使用函數來實現可重複使用性,因為兩者都允許程式碼重複使用。然而,如果我們直接在組件中使用函數,可能會導致它們之間的緊密耦合。這意味著函數或其邏輯的任何變化都可能影響它使用的每個地方。

依賴注入透過將依賴項的建立與使用它們的元件解耦來解決這個問題,使程式碼更易於維護和測試。

沒有依賴注入的範例

function getProperty<Type>(obj: Type, key: keyof Type) {
  return obj[key];
}

let x = { a: 1, b: 2, c: 3 };
getProperty(x, "a");  // Valid
getProperty(x, "d");  // Error: Argument of type '"d"' is not assignable to parameter of type '"a" | "b" | "c"'.

登入後複製
登入後複製

依賴注入範例

function func(param:number|boolean){
return param;
}
console.log(func(2)) //Output: 2 will be printed
console.log(func("True")) //Error: boolean cannot be passed as argument

登入後複製
登入後複製

在緊密耦合的場景中,如果您今天 MentalWellness 類別中有一個stressLevel 屬性,並決定明天將其更改為其他屬性,則需要更新所有使用它的地方。這可能會導致許多重構和維護挑戰。

但是,透過依賴注入和介面的使用,你可以避免這個問題。透過建構函式傳遞依賴項(例如 MentalWellness 服務),具體的實作細節(例如stressLevel 屬性)被抽像到介面後面。這意味著只要介面保持不變,對屬性或類別的變更不需要修改依賴類別。這種方法可確保程式碼鬆散耦合、更易於維護且更易於測試,因為您可以在運行時注入所需的內容,而無需緊密耦合元件。

以上是每個開發人員都應該了解的高級打字稿概念的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1655
14
CakePHP 教程
1413
52
Laravel 教程
1306
25
PHP教程
1252
29
C# 教程
1225
24
前端熱敏紙小票打印遇到亂碼問題怎麼辦? 前端熱敏紙小票打印遇到亂碼問題怎麼辦? Apr 04, 2025 pm 02:42 PM

前端熱敏紙小票打印的常見問題與解決方案在前端開發中,小票打印是一個常見的需求。然而,很多開發者在實...

神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

誰得到更多的Python或JavaScript? 誰得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

如何實現視差滾動和元素動畫效果,像資生堂官網那樣?
或者:
怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? 如何實現視差滾動和元素動畫效果,像資生堂官網那樣? 或者: 怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? Apr 04, 2025 pm 05:36 PM

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? 如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

JavaScript引擎:比較實施 JavaScript引擎:比較實施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

前端開發中如何實現類似 VSCode 的面板拖拽調整功能? 前端開發中如何實現類似 VSCode 的面板拖拽調整功能? Apr 04, 2025 pm 02:06 PM

探索前端中類似VSCode的面板拖拽調整功能的實現在前端開發中,如何實現類似於VSCode...

See all articles