日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無(wú)先后,達(dá)者為師

網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

TypeScript中的泛型(泛型函數(shù)、接口、類、泛型約束)

作者:jieyucx 更新時(shí)間: 2023-07-26 編程語(yǔ)言

一、泛型函數(shù)

TypeScript泛型是一種可以使代碼具有更高的可重用性和泛化能力的特性。通過(guò)泛型,我們可以定義一種通用的類型或函數(shù),使其能夠應(yīng)對(duì)多種類型的輸入。泛型在類、函數(shù)、接口等多種場(chǎng)景下都可以使用。

具體來(lái)說(shuō),在定義泛型函數(shù)時(shí),我們可以使用來(lái)表示一個(gè)類型變量,這樣我們就可以在函數(shù)中使用這個(gè)泛型類型來(lái)作為參數(shù)類型、返回值類型或變量類型等。例如:

function echo<T>(arg: T): T {
    return arg;
}

let myIdentity: <T>(arg: T) => T = echo;

在這個(gè)例子中,我們定義了一個(gè)echo函數(shù),它使用泛型類型變量T作為輸入?yún)?shù)類型和返回值類型,這樣我們就可以使用不同類型的參數(shù)來(lái)調(diào)用該函數(shù),例如:

console.log(echo('Hello TypeScript!')); // 輸出:Hello TypeScript!
console.log(echo(123)); // 輸出:123

二、泛型類

在類的定義中使用泛型,也可以大大提高代碼的復(fù)用性和靈活性。例如下面的代碼:

class Stack<T> {
    private items: T[] = [];

    push(item: T) {
        this.items.push(item);
    }

    pop(): T {
        return this.items.pop();
    }
}

let strStack = new Stack<string>();
strStack.push('apple');
strStack.push('banana');
strStack.push('cherry');

console.log(strStack.pop());
console.log(strStack.pop());
console.log(strStack.pop());

在上面的代碼中,定義了一個(gè)Stack類,并聲明了泛型類型T,用于在push和pop方法中進(jìn)行類型的轉(zhuǎn)換。通過(guò)傳入不同類型的參數(shù),可以得到不同類型的Stack實(shí)例。

三、泛型接口

interface Map<K, V> {
    set(key: K, val: V): void;
    get(key: K): V | undefined;
    has(key: K): boolean;
    clear(): void;
}

let numMap: Map<number, string> = {
    set(key: number, val: string) {
        // 添加鍵值對(duì)
    },
    get(key: number): string | undefined {
        // 獲取鍵值對(duì)
    },
    has(key: number): boolean {
        // 判斷是否存在
    },
    clear() {
        // 清空Map
    }
};

numMap.set(1, 'apple');
numMap.set(2, 'banana');

console.log(numMap.get(1));
console.log(numMap.get(2));

在上面的代碼中,定義了一個(gè)Map接口,并使用泛型K和V來(lái)約束鍵和值的類型。通過(guò)傳入不同類型的參數(shù),可以得到不同類型的Map實(shí)例,并實(shí)現(xiàn)對(duì)不同類型鍵值對(duì)的操作。

四、泛型約束、泛型限制用法<T> extends {屬性:類型}

在 TypeScript 中,泛型約束是一種讓泛型類型參數(shù)只能取某些特定類型的值的機(jī)制。這個(gè)特定類型的限制可以是一個(gè)接口、類、枚舉或其他類型。

例如,假設(shè)我們有一個(gè)泛型函數(shù),它接受一個(gè)類型參數(shù) T 和一個(gè)對(duì)象參數(shù) obj,這個(gè)函數(shù)返回 obj 中的第一個(gè) T 類型的屬性值:

function getPropertyValue<T>(obj: object): T {
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      let value = obj[key];
      if (value instanceof T) {
        return value;
      }
    }
  }
  throw new Error(`No property of type ${T.name} found.`);
}

但是,這個(gè)函數(shù)可能會(huì)遇到一些問(wèn)題。例如,如果我們調(diào)用 getPropertyValue({ a: ‘1’, b: 2, c: 3 }),那么會(huì)拋出一個(gè)錯(cuò)誤,因?yàn)樽址?‘1’ 不是一個(gè) number 類型。

為了解決這個(gè)問(wèn)題,我們可以使用泛型約束來(lái)限制 T 只能取某些特定類型的值。例如,我們可以要求 T 必須是實(shí)現(xiàn)了 Number 接口的類型:

interface Number {
  new (value?: any): number;
  (value?: any): number;
  readonly NaN: number;
  readonly MAX_VALUE: number;
  readonly MIN_VALUE: number;
  readonly NEGATIVE_INFINITY: number;
  readonly POSITIVE_INFINITY: number;
}

function getPropertyValue<T extends Number>(obj: object): T {
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      let value = obj[key];
      if (value instanceof T) {
        return value;
      }
    }
  }
  throw new Error(`No property of type ${T.name} found.`);
}

現(xiàn)在,如果我們調(diào)用 getPropertyValue({ a: ‘1’, b: 2, c: 3 }),就會(huì)得到一個(gè)類型錯(cuò)誤,因?yàn)?‘1’ 不是一個(gè)實(shí)現(xiàn)了 Number 接口的類型。但是,如果我們調(diào)用 getPropertyValue({ a: 1, b: 2, c: 3 }),就能得到正確的結(jié)果了。

另一泛型約束\<key extends keyof Type>

在 TypeScript 中,<key extends keyof Type> 是一種泛型約束方式,用于限制一個(gè)泛型類型參數(shù) key 的范圍。

其中,keyof 關(guān)鍵字可以用于獲取一個(gè)類型 Type 的所有屬性名,返回一個(gè)字符串字面量類型,例如:

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

type PersonKeys = keyof Person; // "name" | "age"

<key extends keyof Type> 中,extends 關(guān)鍵字表示限制 key 的取值只能是 Type 類型中已有的屬性名。也就是說(shuō),只有 key 取值為 Type 類型中已有的屬性名才符合類型約束,例如:

function getValueByKey<T extends object, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const person = {
  name: 'Bob',
  age: 25,
};
const name = getValueByKey(person, 'name'); // name 的類型是 string
const age = getValueByKey(person, 'age'); // age 的類型是 number
const gender = getValueByKey(person, 'gender'); // 編譯報(bào)錯(cuò),gender 不是 person 中的屬性

在上面的例子中,getValueByKey 函數(shù)接收兩個(gè)參數(shù):一個(gè)泛型類型參數(shù) T,代表輸入對(duì)象的類型;一個(gè)泛型類型參數(shù) K,代表屬性名的類型。

extends keyof T 約束了類型參數(shù) K 必須是輸入對(duì)象類型 T 中已存在的屬性名。因此,調(diào)用 getValueByKey 函數(shù)傳入一個(gè)不存在的屬性名 gender 會(huì)引發(fā)編譯錯(cuò)誤。

五、使用泛型注意點(diǎn)

在編寫泛型方法時(shí),應(yīng)該注意以下幾點(diǎn):

  1. 泛型形參的名稱應(yīng)該描述清楚其作用和范圍,盡量不要使用單個(gè)字母的形參名稱;
  2. 在使用泛型類型的屬性或方法時(shí),應(yīng)該確保該屬性或方法在所有可能的泛型類型中都是存在的,不要使用不存在的屬性或方法;
  3. 在使用泛型類型的操作符時(shí),應(yīng)該考慮不同類型之間可能的差異性和兼容性問(wèn)題,避免出現(xiàn)類型錯(cuò)誤

原文鏈接:https://blog.csdn.net/jieyucx/article/details/131346916

  • 上一篇:沒(méi)有了
  • 下一篇:沒(méi)有了
欄目分類
最近更新