最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

TypeScript 泛型四大應(yīng)用場景與高級用法

 更新時(shí)間:2026年01月20日 10:09:05   作者:如果你好  
TypeScript中的泛型是一種靈活的類型系統(tǒng)工具,可以在函數(shù)、接口、類和類型別名中使用,以實(shí)現(xiàn)一次定義多類型復(fù)用,它提供了類型參數(shù)和類型約束,確保類型安全同時(shí)保留類型信息,下面就來介紹一下如何使用,感興趣的可以了解一下

一、TypeScrip寫法

泛型是 TypeScript 中一種「類型化的變量」,它不預(yù)先指定具體的類型,而是在使用時(shí)才確定類型。簡單來說,泛型就像一個(gè)「類型占位符」,可以在函數(shù)、接口、類、類型別名中被復(fù)用,從而實(shí)現(xiàn)一套代碼適配多種類型,同時(shí)避免 any 類型帶來的類型信息丟失。

舉個(gè)簡單的例子:如果我們需要一個(gè)函數(shù),能夠返回?cái)?shù)組的第一個(gè)元素,同時(shí)支持?jǐn)?shù)字?jǐn)?shù)組、字符串?dāng)?shù)組等多種類型,不用泛型的話,要么寫多個(gè)重載函數(shù),要么使用 any 類型:

// 弊端:丟失類型校驗(yàn),返回值為 any 類型
function getFirst(arr: any[]): any {
  return arr[0];
}

const str = getFirst(["a", "b", "c"]); // 類型為 any,無法獲得自動(dòng)補(bǔ)全
const num = getFirst([1, 2, 3]); // 類型為 any,存在類型安全風(fēng)險(xiǎn)

而使用泛型,我們可以完美解決這個(gè)問題:

// 泛型基礎(chǔ)寫法:用 <T> 定義類型參數(shù),T 可看作任意合法的類型變量名
function getFirst<T>(arr: T[]): T {
  return arr[0];
}

// 使用時(shí)自動(dòng)推導(dǎo)類型,也可顯式指定類型
const str = getFirst(["a", "b", "c"]); // 自動(dòng)推導(dǎo) T 為 string,返回值類型為 string
const num = getFirst<number>([1, 2, 3]); // 顯式指定 T 為 number,返回值類型為 number

這里的 <T> 就是泛型的核心標(biāo)識,T(Type 的縮寫,也可以用 U、V、Data 等任意合法名稱)就是我們定義的「類型參數(shù)」,它會在函數(shù)調(diào)用時(shí)被具體的類型替代,從而實(shí)現(xiàn)「一次定義,多類型復(fù)用」。

二、泛型的四大核心應(yīng)用場景

泛型的應(yīng)用場景主要集中在函數(shù)、接口、類、類型別名這四個(gè)方面,下面逐一拆解每種場景的寫法與實(shí)戰(zhàn)用法。

場景 1:泛型函數(shù)(最常用)

泛型函數(shù)是日常開發(fā)中使用頻率最高的場景,核心寫法是「在函數(shù)名后添加 <類型參數(shù)>」,類型參數(shù)可以在函數(shù)的參數(shù)、返回值、內(nèi)部變量中使用。

基礎(chǔ)寫法

// 單個(gè)類型參數(shù)
function wrapValue<T>(value: T): { value: T } {
  return { value };
}

// 多個(gè)類型參數(shù)(支持定義多個(gè)泛型變量,用逗號分隔)
function mergeObjects<U, V>(obj1: U, obj2: V): U & V {
  return { ...obj1, ...obj2 };
}

// 實(shí)戰(zhàn)使用
const wrapped = wrapValue<boolean>(true); // 返回 { value: boolean }
const merged = mergeObjects({ name: "張三" }, { age: 28 }); // 返回 { name: string; age: number }

關(guān)鍵特性:類型參數(shù)的默認(rèn)值

和函數(shù)參數(shù)可以設(shè)置默認(rèn)值一樣,泛型的類型參數(shù)也可以設(shè)置默認(rèn)值。當(dāng)使用泛型時(shí)沒有顯式指定類型參數(shù),且 TypeScript 無法自動(dòng)推導(dǎo)時(shí),會使用這個(gè)默認(rèn)值。

語法:<T = 默認(rèn)類型>

// 為類型參數(shù) T 設(shè)置默認(rèn)值 string
function getFirst<T = string>(arr: T[]): T {
  return arr[0];
}

// 未顯式指定類型,且無法推導(dǎo)具體類型時(shí),使用默認(rèn)值 string
const defaultVal = getFirst([]); // T 為 string,返回值類型為 string

// 自動(dòng)推導(dǎo)類型,覆蓋默認(rèn)值
const numVal = getFirst([1, 2, 3]); // T 為 number,返回值類型為 number

場景 2:泛型接口

當(dāng)接口需要支持多種類型的屬性或方法時(shí),泛型接口可以讓接口具備更強(qiáng)的復(fù)用性。核心寫法是「在接口名后添加 <類型參數(shù)>」,類型參數(shù)可用于接口的屬性、方法參數(shù)和返回值。

基礎(chǔ)寫法

// 定義泛型接口
interface Result<T> {
  code: number;
  message: string;
  data: T; // 用泛型 T 定義 data 屬性的類型
}

// 使用時(shí)指定具體類型
type UserResult = Result<{ id: number; name: string }>;
type ArticleResult = Result<{ title: string; content: string }>;

// 實(shí)戰(zhàn)應(yīng)用:接口返回值類型定義
const userRes: UserResult = {
  code: 200,
  message: "請求成功",
  data: { id: 1, name: "張三" }
};

const articleRes: ArticleResult = {
  code: 200,
  message: "請求成功",
  data: { title: "TypeScript 泛型指南", content: "泛型的四大應(yīng)用場景..." }
};

泛型接口與函數(shù)結(jié)合(常用實(shí)戰(zhàn)場景)

// 定義泛型接口(描述函數(shù)類型)
interface RequestFunction<T> {
  (url: string): Promise<Result<T>>;
}

// 實(shí)現(xiàn)該接口的函數(shù)
const getUserInfo: RequestFunction<{ id: number; name: string }> = async (url) => {
  const res = await fetch(url);
  return res.json();
};

帶默認(rèn)值的泛型接口

// 為泛型接口設(shè)置默認(rèn)值
interface Pagination<T = unknown> {
  page: number;
  size: number;
  total: number;
  list: T[];
}

// 未指定類型,使用默認(rèn)值 unknown
const defaultPagination: Pagination = {
  page: 1,
  size: 10,
  total: 100,
  list: []
};

// 指定具體類型,覆蓋默認(rèn)值
const userPagination: Pagination<{ id: number; name: string }> = {
  page: 1,
  size: 10,
  total: 100,
  list: [{ id: 1, name: "張三" }]
};

場景 3:泛型類

泛型類適用于「類的屬性、方法需要支持多種類型」的場景,比如數(shù)據(jù)容器、隊(duì)列、棧等。核心寫法是「在類名后添加 <類型參數(shù)>」,類型參數(shù)可用于類的屬性、構(gòu)造函數(shù)、實(shí)例方法。

基礎(chǔ)寫法

// 定義泛型類
class Stack<T> {
  private items: T[] = [];

  // 入棧方法
  push(item: T): void {
    this.items.push(item);
  }

  // 出棧方法
  pop(): T | undefined {
    return this.items.pop();
  }

  // 獲取棧頂元素
  peek(): T | undefined {
    return this.items[this.items.length - 1];
  }
}

// 使用時(shí)指定具體類型
const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
console.log(numberStack.pop()); // 2(類型為 number | undefined)

const stringStack = new Stack<string>();
stringStack.push("a");
stringStack.push("b");
console.log(stringStack.peek()); // "b"(類型為 string | undefined)

帶默認(rèn)值的泛型類

// 為泛型類設(shè)置默認(rèn)值
class Container<T = string> {
  private data: T;

  constructor(data: T) {
    this.data = data;
  }

  getData(): T {
    return this.data;
  }
}

// 未指定類型,使用默認(rèn)值 string
const defaultContainer = new Container("hello");
console.log(defaultContainer.getData()); // "hello"(類型為 string)

// 指定具體類型,覆蓋默認(rèn)值
const numberContainer = new Container<number>(123);
console.log(numberContainer.getData()); // 123(類型為 number)

注意:泛型類只作用于實(shí)例部分,靜態(tài)屬性和靜態(tài)方法無法使用類的泛型參數(shù)(因?yàn)殪o態(tài)成員屬于類本身,而泛型參數(shù)是在實(shí)例化時(shí)確定的)。

場景 4:泛型類型別名

類型別名(type)是 TypeScript 中定義自定義類型的重要方式,泛型類型別名可以讓自定義類型具備更強(qiáng)的靈活性,核心寫法是「在類型別名后添加 <類型參數(shù)>」。

基礎(chǔ)寫法

// 定義泛型類型別名
type Pair<T> = [T, T]; // 元組類型,兩個(gè)元素類型相同
type Optional<T> = T | undefined; // 可選類型,T 或 undefined
type RecordMap<K extends string | number, V> = { [key in K]: V }; // 映射類型

// 使用時(shí)指定具體類型
type NumberPair = Pair<number>; // [number, number]
type OptionalString = Optional<string>; // string | undefined
type UserMap = RecordMap<number, { name: string; age: number }>; // { [key: number]: { name: string; age: number } }

// 實(shí)戰(zhàn)應(yīng)用
const pair: NumberPair = [1, 2];
const optionalStr: OptionalString = "hello";
const userMap: UserMap = {
  1: { name: "張三", age: 28 },
  2: { name: "李四", age: 30 }
};

帶默認(rèn)值的泛型類型別名

// 為泛型類型別名設(shè)置默認(rèn)值
type ResponseData<T = { [key: string]: unknown }> = {
  success: boolean;
  data: T;
};

// 未指定類型,使用默認(rèn)值
const defaultResponse: ResponseData = {
  success: true,
  data: { id: 1, name: "張三" }
};

// 指定具體類型,覆蓋默認(rèn)值
const userResponse: ResponseData<{ id: number; name: string }> = {
  success: true,
  data: { id: 1, name: "張三" }
};

三、高級用法:類型參數(shù)的約束條件

在某些場景下,我們不希望泛型參數(shù)是「任意類型」,而是希望它滿足一定的約束條件(比如擁有某個(gè)屬性、實(shí)現(xiàn)某個(gè)接口)。這時(shí)可以使用 extends 關(guān)鍵字來約束泛型參數(shù),這就是「泛型約束」。

基礎(chǔ)約束:extends 關(guān)鍵字

// 定義一個(gè)接口,作為約束條件
interface HasLength {
  length: number;
}

// 約束 T 必須實(shí)現(xiàn) HasLength 接口(即 T 必須擁有 length 屬性)
function getLength<T extends HasLength>(value: T): number {
  return value.length;
}

// 合法:string 擁有 length 屬性
console.log(getLength("hello")); // 5

// 合法:數(shù)組擁有 length 屬性
console.log(getLength([1, 2, 3])); // 3

// 合法:自定義對象擁有 length 屬性
console.log(getLength({ length: 10, name: "測試" })); // 10

// 不合法:number 沒有 length 屬性,編譯報(bào)錯(cuò)
console.log(getLength(123)); // Error: Argument of type 'number' is not assignable to parameter of type 'HasLength'

泛型約束與默認(rèn)值結(jié)合

泛型約束和默認(rèn)值可以同時(shí)使用,語法順序?yàn)椤?code><T extends 約束類型 = 默認(rèn)類型>」:

interface HasId {
  id: number;
}

// 約束 T 必須實(shí)現(xiàn) HasId 接口,同時(shí)設(shè)置默認(rèn)值
function getId<T extends HasId = { id: number; name: string }>(obj: T): number {
  return obj.id;
}

// 未指定類型,使用默認(rèn)值(滿足 HasId 約束)
const defaultId = getId({ id: 1, name: "張三" }); // 1

// 指定具體類型(滿足 HasId 約束)
const customId = getId({ id: 2, age: 28 }); // 2

常用約束:約束為對象、字符串/數(shù)字字面量

// 約束 T 為對象類型
function getProperty<T extends object, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const user = { name: "張三", age: 28 };
console.log(getProperty(user, "name")); // "張三"(類型為 string)
console.log(getProperty(user, "age")); // 28(類型為 number)

// 約束 K 為 "success" | "error" 字面量類型
function createMessage<K extends "success" | "error" = "success">(type: K): { type: K; content: string } {
  return {
    type,
    content: type === "success" ? "操作成功" : "操作失敗"
  };
}

const successMsg = createMessage(); // { type: "success"; content: string }
const errorMsg = createMessage("error"); // { type: "error"; content: string }

四、泛型使用總結(jié)與最佳實(shí)踐

  1. 泛型的核心價(jià)值:復(fù)用代碼、保留類型信息、避免 any 類型,實(shí)現(xiàn)「靈活與安全并存」。
  2. 四大應(yīng)用場景優(yōu)先級:泛型函數(shù) > 泛型接口 > 泛型類型別名 > 泛型類(類的泛型使用場景相對有限)。
  3. 最佳實(shí)踐
    • 類型參數(shù)命名盡量語義化(如 T 表示通用類型,U/V 表示輔助類型,K 表示鍵類型,V 表示值類型)。
    • 對于有常用類型的場景,設(shè)置泛型默認(rèn)值,提升代碼易用性。
    • 當(dāng)需要限制泛型范圍時(shí),使用 extends 進(jìn)行約束,避免非法類型傳入。
    • 避免過度泛型化:如果一個(gè)函數(shù)只需要支持一種或兩種固定類型,無需使用泛型,直接定義具體類型即可。

到此這篇關(guān)于TypeScript 泛型四大應(yīng)用場景與高級用法的文章就介紹到這了,更多相關(guān)TypeScript 泛型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 改變隱藏的input中value的值代碼

    改變隱藏的input中value的值代碼

    本文為大家介紹下如何改變隱藏的input中value的值,一句代碼就可以實(shí)現(xiàn),感性的朋友可以參考下
    2013-12-12
  • 小程序rich-text組件如何改變內(nèi)部img圖片樣式的方法

    小程序rich-text組件如何改變內(nèi)部img圖片樣式的方法

    這篇文章主要介紹了小程序rich-text組件如何改變內(nèi)部img圖片樣式的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-05-05
  • ECharts入門教程

    ECharts入門教程

    ECharts 是一個(gè)使用JavaScript實(shí)現(xiàn)的開源可視化庫,涵蓋各行業(yè)圖表,滿足各種需求。這篇文章介紹了ECharts的基礎(chǔ)知識,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • JavaScript提高性能知識點(diǎn)匯總

    JavaScript提高性能知識點(diǎn)匯總

    這篇文章主要為大家介紹了JavaScript幾個(gè)提高性能知識點(diǎn),感興趣的小伙伴們可以參考一下
    2016-01-01
  • JS封裝的自動(dòng)創(chuàng)建表格的實(shí)現(xiàn)代碼

    JS封裝的自動(dòng)創(chuàng)建表格的實(shí)現(xiàn)代碼

    這篇文章主要介紹了JS封裝的自動(dòng)創(chuàng)建表格的實(shí)現(xiàn)代碼的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • 基于p5.js實(shí)現(xiàn)色彩輪和餅狀圖的動(dòng)態(tài)可視化

    基于p5.js實(shí)現(xiàn)色彩輪和餅狀圖的動(dòng)態(tài)可視化

    這篇文章主要介紹了基于p5.js實(shí)現(xiàn)色彩輪和餅狀圖的動(dòng)態(tài)可視化,文中給出了詳細(xì)的代碼,它適用于需要展示顏色信息或數(shù)據(jù)分布情況的場景,如設(shè)計(jì)、數(shù)據(jù)分析和教育領(lǐng)域,感興趣的朋友可以參考下
    2024-06-06
  • XMLHttpRequest對象_Ajax異步請求重點(diǎn)(推薦)

    XMLHttpRequest對象_Ajax異步請求重點(diǎn)(推薦)

    下面小編就為大家?guī)硪黄猉MLHttpRequest對象_Ajax異步請求重點(diǎn)(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • javascript prototype的深度探索不是原型繼承那么簡單

    javascript prototype的深度探索不是原型繼承那么簡單

    JavaScript中對象的prototype屬性,可以返回對象類型原型的引用。這是一個(gè)相當(dāng)拗口的解釋,要理解它,先要正確理解對象類型(Type)以及原型(prototype)的概念。
    2008-06-06
  • 兼容IE和FF的圖片上傳前預(yù)覽js代碼

    兼容IE和FF的圖片上傳前預(yù)覽js代碼

    上傳前預(yù)覽使用js實(shí)現(xiàn)還是比較cool的,同時(shí)還可以兼容IE和FF的能做到這一點(diǎn)已經(jīng)相當(dāng)不容易了,下面與大家一起分享下具體的實(shí)現(xiàn),感興趣的你可不要錯(cuò)過了哈
    2013-05-05
  • JavaScript判斷輸入是否為整數(shù)的正則表達(dá)式

    JavaScript判斷輸入是否為整數(shù)的正則表達(dá)式

    這篇文章主要介紹了JavaScript判斷輸入是否為整數(shù)的正則表達(dá)式,用于驗(yàn)證不同類型的數(shù)據(jù),包括數(shù)字、字符、電子郵件、網(wǎng)址、身份證號、手機(jī)號碼等,每個(gè)模式都提供了詳細(xì)的正則表達(dá)式和匹配說明,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-04-04

最新評論

新泰市| 衡阳县| 武汉市| 资中县| 光泽县| 临沧市| 柯坪县| 遵化市| 保亭| 长春市| 广水市| 桓台县| 城口县| 贵德县| 若羌县| 乐亭县| 扎囊县| 平舆县| 上思县| 龙口市| 屏东市| 丁青县| 沅陵县| 泗洪县| 洛川县| 株洲市| 寿阳县| 宁远县| 连南| 余干县| 梅河口市| 定安县| 东阳市| 贺兰县| 乐都县| 莱阳市| 高尔夫| 阿城市| 利川市| 马关县| 阜新|