精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

使用條件類型與 infer 在 TypeScript 中構建類型化 fetch

開發 前端
extends在類型聲明中不是陳述而是提問:"schema[P][M]是否擴展了這個對象?"如果條件為真,返回?后的類型;否則返回:后的類型。

最近,我在處理基于 OpenAPI 模式生成的 API 請求和響應類型時,發現可以利用 TypeScript 的條件類型, 讓 fetch 邏輯能根據調用的路徑和使用的 HTTP 方法自動推斷出合適的參數和響應類型,這確實非常酷。我查閱 了文檔想了解更多,卻發現文檔對這種類型推斷的介紹并不深入,因此決定分享這個實用技巧。

type GetReturnType<Type> = Type extends (...args: never[]) => infer Return ? Return : never;

本文將展示 TypeScript 如何通過extends和infer關鍵字從復雜嵌套結構中智能提取類型。

前置知識

本文假設您已了解TypeScript 泛型的基本概念。

條件類型:編譯器的決策機制

條件類型就像是 TypeScript 中的 if 語句:"如果滿足這個條件,就是「這種」類型,否則是「那種」類型"。其語法類似 JavaScript 的三元運算符,特別適用于需要根據輸入返回不同類型的函數:

type myFn = (arg: SomeType | OtherType) => arg extends SomeType ? string : number;

extends在類型聲明中不是陳述而是提問:"schema[P][M]是否擴展了這個對象?"如果條件為真,返回?后的類型;否則返回:后的類型。

infer 關鍵字:類型提取利器

雖然TypeScript 文檔對infer的介紹不多,但它能優雅地提取函數返回類型:

type GetReturnType<Type> = Type extends (...args: never[]) => infer Return ? Return : never;

type Num = GetReturnType<() => number>; // number
type Str = GetReturnType<(x: string) => string>; // string
type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>; // boolean[]

這個關鍵字相當于告訴編譯器:"你告訴我這是什么類型,我不想全部寫出來"。在處理具有相同屬性不同組合的多種類型時特別有用。

調試技巧

由于 TypeScript 缺少類型調試器,我通常通過 VSCode的IntelliSense來檢查類型:

type MyComplexType<T,Q> = {....}
type test = MyComplexType<"test value", "another test value">

示例項目:鳥類觀測網站

我們正在構建一個鳥類觀測網站,需要確保 API 請求包含正確參數,并以類型安全的方式使用返回數據。以下是簡化的 API 模式:

export interface schema {
'/birds': {
    get: {
      parameters: {
        query?: {
          type?: string; // 按類型篩選
          habitat?: string; // 按棲息地篩選
          colour?: string; // 按顏色篩選
        };
      };
      response: {
        content: {
          id?: number;
          name?: string; // 如"Avocet"
          type?: string; // 如"wader"
          habitats?: string[]; // 如["lakes","wetlands"]
          colours?: string[];
          distinctiveFeatures?: string;
          wingspan?: number; // 翼展(厘米)
          image?: string; // 圖片URL
        };
      };
    };
  };
'/users': {
    post: {
      requestBody?: {
        content: {
          name?: string; // 用戶名
          email?: string; // 郵箱
          favouriteBird?: number[]; // 收藏的鳥類ID
        };
      };
      response: {
        content: {
          id?: number;
          name?: string; // 如"Billie Sandpiper"
          favouriteBirds?: number[]; // 如[12,14]
          email?: string; // 如"billie@example.com"
        };
      };
    };
  };
}

原生 fetch 的局限性

原生fetch無法利用我們定義的類型:

const rsp = await fetch('https://api.example.com/bird/12');
const data = await rsp.json(); // 此時不知道具體類型

而且fetch不是泛型函數,不能直接指定請求和響應類型:

await fetch<GetBirdRequest, GetBirdResponse>(...)  // 這樣不行

雖然可以手動指定返回類型,但很繁瑣:

const data = (await rsp.json()) as schema['/bird/{birdId}']['get']['response']['content'];

構建 createFetcher 函數

我們將創建一個createFetcher高階函數,根據路徑和 HTTP 方法返回知道具體參數和返回類型的函數:

function createFetcher(path, method) {
    return async (params) => { // ... }
}

const getBird = createFetcher('/birds/{birdId}', 'get')
const data = await getBird({ path: { birdId: 12 } })

參數錯誤時會得到明確的類型提示:

const data = await getBird({});
// 錯誤:缺少必需的path參數

實現細節

  1. 基礎結構:
import { schema } from'./api';

function createFetcher<P extends keyof schema, M extends keyof schema[P]>(path: P, method: M) {
returnasync (params) => {
    const baseUrl = 'https://api.example.com';
    const fetchUrl = newURL(path, baseUrl);
    constoptions: RequestInit = { method: method asstring };
    const data = awaitfetch(fetchUrl, options);
    returnawait data.json();
  };
}
  1. 參數類型推斷:
type Params<P extends keyof schema, M extends keyof schema[P]> = schema[P][M] extends {
parameters: {
    query?: infer Q;
    path?: infer PP;
    requestBody?: { content: infer RB };
  };
}
  ? {
      query?: Q extendsundefined ? never : Q;
      path: PP;
      requestBody?: RBextendsundefined ? never : RB;
    }
  : never;
  1. 路徑參數替換:
const pathParams = path.match(/{([^}]+)}/g);
let realPath = path as string;
pathParams?.forEach((param) => {
  const paramName = param.replace(/{|}/g, '');
  realPath = realPath.replace(param, params?.path?.[paramName]);
});
  1. 處理查詢參數和請求體:
if (params?.query) {
  Object.entries(params.query).forEach(([key, value]) => {
    fetchUrl.searchParams.append(key, value as string);
  });
}

if (params?.requestBody) {
  options.body = JSON.stringify(params.requestBody);
  options.headers = { 'Content-Type': 'application/json' };
}
  1. 響應類型處理:
type ResponseT<P extends keyof schema, M extends keyof schema[P]> = schema[P][M] extends {
  response: { content: infer R };
}
  ? R
  : never;

return fetch(fetchUrl, options).then((res) => res.json() as ResponseT<P, M>);

最終成果

const listBirds = createFetcher('/birds', 'get');
const allBirds = awaitlistBirds();

const getBird = createFetcher('/birds/{birdId}', 'get');
const bird = awaitgetBird({ path: { birdId: 12 } });

const addSighting = createFetcher('/users/{userId}/sightings', 'post');
const mySighting = awaitaddSighting({
path: { userId: 1 },
requestBody: {
    birdId: 226,
    timestamp: '2025-06-04T13:00:00Z',
    lat: 51.4870924,
    long: 0.2228486,
    notes: '在樹上聽到它的歌聲!',
  },
});

通過條件類型和infer,我們成功創建了完全類型化的 fetch 函數,使 API 調用更加安全和便捷。

原文地 址:https://piccalil.li/blog/building-a-typed-fetch-in-typescript-with-conditional-types-and-infer/作者:Sophie Koonin

責任編輯:武曉燕 來源: 前端小石匠
相關推薦

2024-05-11 10:19:31

TypeScript類型接口

2021-07-27 06:06:34

TypeScript語言運算符

2023-07-04 15:11:30

TypeScript類型保護

2022-08-08 09:00:42

TypeScript映射類型

2022-04-11 08:42:09

TypeScript子類型定義

2022-09-20 14:43:55

TypeScript類型體操

2022-08-19 12:12:02

TypeScriptInfer 類型

2023-09-27 10:19:37

類型video函數

2022-05-04 09:02:41

TypeScript類型工具

2022-02-25 09:06:02

TypeScripnever工具

2024-08-12 08:50:17

2017-03-28 15:30:51

服務器虛擬化內存

2017-04-17 14:40:11

虛擬化服務器內存

2020-12-18 11:35:22

TypeScript語言Java

2022-04-10 19:26:07

TypeScript類型語法

2010-04-01 10:55:48

Oracle 數據類型

2021-06-09 07:55:19

Typescript類型檢查

2021-12-10 08:21:15

TypeScript高級類型類型體操

2022-06-05 23:28:50

TypeScripinfer類型

2021-08-18 07:56:05

Typescript類型本質
點贊
收藏

51CTO技術棧公眾號

影音先锋成人资源网站| 久久午夜鲁丝片午夜精品| 无码国产伦一区二区三区视频| 久久最新网址| 国产精品一区二区不卡| 亚洲色图第三页| 国产精品区免费视频| 奇米网一区二区| 在线观看v片| 岛国av在线一区| 久久艳片www.17c.com| 国产又大又黄又粗的视频| 视频一区二区免费| 欧美三级小说| 91精品国产综合久久小美女| 视频一区免费观看| 狠狠人妻久久久久久综合| 91精品国产自产精品男人的天堂| 成人免费在线视频观看| 国产精品国内视频| 三上悠亚影音先锋| xx欧美视频| 久久精品一区二区三区av| 51久久精品夜色国产麻豆| 国产人妻黑人一区二区三区| 欧美videos另类精品| 亚洲中无吗在线| 欧美精品久久久久久久久老牛影院| 日韩hmxxxx| 五月婷婷激情视频| 好看的av在线不卡观看| 精品国产欧美一区二区| www..com日韩| 国产精品久久777777换脸| 91免费精品| 欧美日韩黄色一区二区| 国产一级二级毛片| 亚洲av永久无码国产精品久久| 亚洲乱码一区| 91福利国产成人精品照片| 精品午夜一区二区三区| 91久久国产精品| 李丽珍裸体午夜理伦片| 高清一区二区中文字幕| 亚洲色图在线视频| 91久久爱成人| 国产小视频在线免费观看| 红桃成人av在线播放| 在线国产电影不卡| 中文字幕免费高| 亚洲精选一区二区三区| 国产一区91精品张津瑜| 韩国精品久久久999| 在线国产视频一区| 另类视频一区二区三区| 亚洲成av人片在www色猫咪| 久久综合伊人77777麻豆| 伊人精品一区二区三区| 亚洲精品1区| 色噜噜狠狠狠综合曰曰曰| 久久黄色一级视频| 2022成人影院| 第一福利永久视频精品 | 免费麻豆国产一区二区三区四区| 国产精东传媒成人av电影| 欧美午夜丰满在线18影院| 亚洲精品影院| 头脑特工队2免费完整版在线观看| 奇米色777欧美一区二区| 欧美乱妇高清无乱码| 超碰97在线资源站| 欧美aaaaaa| 精品久久香蕉国产线看观看gif| 制服国产精品| 免费一级在线观看| 国产精品一区免费视频| 亚洲综合在线播放| 中文字幕在线天堂| 精品999网站| 自拍偷拍亚洲在线| 欲求不满的岳中文字幕| 一区二区三区日本久久久| 日韩视频免费观看高清完整版在线观看 | 午夜精品久久久久久久第一页按摩| 免费一级欧美片在线播放| 久久亚洲私人国产精品va| 欧美成人黄色网| 国产精品国产一区| 国产亚洲欧美另类中文| 无码人妻一区二区三区在线| av成人在线网站| 欧美性xxxxxxxx| 国产精品亚洲二区在线观看| 蜜桃视频网站在线| 国产亚洲精品7777| 免费看污久久久| 日本在线视频观看| 久久久久久一二三区| 日本a级片久久久| 天堂中文在线8| 国产精品电影一区二区三区| 日本日本精品二区免费| 国产网站在线免费观看| 中文字幕一区二区三| 久草视频这里只有精品| 日本不卡影院| 欧美亚洲一区三区| 亚洲一区二区中文字幕在线观看| 日韩欧美2区| 色8久久精品久久久久久蜜| 色婷婷激情视频| 精品久久91| 国产亚洲欧美日韩美女| 久久成人国产精品入口| 日本视频中文字幕一区二区三区| caoporn国产精品免费公开| 国产白浆在线观看| 狠狠色丁香久久婷婷综合_中 | 91蝌蚪porny| 九色91视频| 日韩一区二区三区中文字幕| 2020日本不卡一区二区视频| 国产一区二区三区18| 亚洲少妇xxx| 久久网站免费观看| 欧美超级免费视 在线| 黄色香蕉视频在线观看| 亚洲午夜精品一区二区国产 | 中文字幕日韩一级| 日韩午夜免费视频| 欧美中文在线观看国产| 精产国品一区二区| 蜜臀av性久久久久蜜臀av麻豆| 国产色视频一区| 亚洲视频中文字幕在线观看| 国产在线一区观看| 天堂资源在线亚洲视频| 欧美人体一区二区三区| 欧美日韩成人一区| 亚洲AV无码片久久精品| 国产欧美日韩亚洲一区二区三区| 奇米成人av国产一区二区三区| 国产成人自拍一区| 久久久噜噜噜久噜久久综合| 国产午夜福利100集发布| 欧美影院在线| 精品久久99ma| 女人又爽又黄免费女仆| 国产日韩欧美一区| 久久九九视频| 高潮一区二区| 一本色道久久88亚洲综合88| 黄色片在线观看网站| 国产免费成人| 欧美激情视频一区二区三区| 免费在线看a| 欧美精品1区2区3区| 色噜噜日韩精品欧美一区二区| 日韩亚洲精品在线| 久久亚洲高清| 国产精品蜜月aⅴ在线| www.亚洲一区| 无码人妻精品一区二区蜜桃色欲| 91亚洲国产成人精品一区二区三| 日本免费不卡一区二区| 日韩美香港a一级毛片| 亚洲国产精品专区久久| 开心激情五月网| 精品影视av免费| 欧美日韩国产精品一卡| 日本欧美日韩| 久久综合电影一区| 深夜福利视频网站| 色94色欧美sute亚洲13| 精品国产视频一区二区三区| 高清成人在线观看| 中文字幕日韩精品久久| 国产免费av国片精品草莓男男| 久久九九免费视频| 国产一级18片视频| 国产成人久久精品77777最新版本| 日韩欧美亚洲精品| 亚洲青青一区| 韩剧1988在线观看免费完整版| 伦理片一区二区三区| 欧美另类久久久品| 久久视频免费在线观看| 国产又黄又大久久| 欧美黑人经典片免费观看| 国产一区日韩| 91中文字精品一区二区| 成人片免费看| 久久99精品国产99久久6尤物| 亚洲av成人精品日韩在线播放| 欧美系列亚洲系列| 久久精品免费在线| 国产成人精品免费| 亚洲爆乳无码专区| 国产精品久久| 亚洲精美视频| 美女av一区| 国产69精品久久久久9| 性欧美8khd高清极品| 狠狠躁18三区二区一区| 国产suv精品一区二区68| 91在线视频播放| 人妻少妇被粗大爽9797pw| 久久丝袜视频| 91中文精品字幕在线视频| 在线观看爽视频| 欧美激情奇米色| 日韩在线观看视频网站| 亚洲成av人片在线观看无码| 国产视频不卡在线| 麻豆精品国产91久久久久久| 亚洲欧洲精品一区二区| 台湾佬综合网| 日韩美女免费视频| 91视频在线观看| 欧美日韩国产a| 欧美福利视频一区二区| 亚洲精品乱码久久久久久黑人| 国产资源中文字幕| 一区在线观看| 91精品国产吴梦梦| 欧美高清视频在线观看mv| 欧美日韩免费精品| 欧美天堂社区| 国产精品欧美久久久| 免费网站看v片在线a| 亚洲精品一区二三区不卡| 又污又黄的网站| 91官网在线免费观看| 成人免费看片98欧美| 亚洲国产成人av好男人在线观看| 亚洲精品乱码久久| 国产91精品露脸国语对白| 欧美激情第一区| 韩国精品免费视频| 天天爽人人爽夜夜爽| 欧美不卡一区| 久久亚洲一区二区| 亚洲黄色录像| 欧美不卡在线一区二区三区| 青青一区二区| 久久婷婷开心| 中国av一区| 日本一区二区三区视频在线播放| 少妇精品久久久一区二区| 美女黄毛**国产精品啪啪| 蜜桃国内精品久久久久软件9| 欧美成人dvd在线视频| 蜜臀91精品国产高清在线观看| 免费精品视频一区| 国产亚洲精品美女久久久久久久久久| 欧美午夜精品久久久久久蜜| 国产毛片一区二区三区| 亚洲一区二区不卡视频| 国产精品1luya在线播放| 俄罗斯精品一区二区| 天然素人一区二区视频| 国产精品日韩在线| avtt久久| 国产一区二区三区av在线| 日韩电影精品| 91免费福利视频| 国内精品国产成人国产三级粉色 | 日韩啪啪电影网| 国产原创精品| 女人丝袜激情亚洲| 亚洲欧洲三级| 国产一区二区三区自拍| 欧美日韩亚洲一| 欧美三区美女| 欧美三级一级片| 麻豆精品新av中文字幕| 佐山爱在线视频| 91免费在线播放| 久久久久人妻一区精品色| 26uuu另类欧美| 五月激情四射婷婷| 艳妇臀荡乳欲伦亚洲一区| 人与动物性xxxx| 亚洲成av人片| 亚洲一线在线观看| 精品成人佐山爱一区二区| 国产系列在线观看| 亚洲欧美日韩国产成人| 日本黄色免费视频| 日韩网站在线观看| av在线加勒比| 高清亚洲成在人网站天堂| 成人性生交大片免费观看网站| 成人激情视频免费在线| 欧美人与性动交xxⅹxx| 97se亚洲综合在线| 欧美裸体在线版观看完整版| 日韩中文字幕在线不卡| 婷婷激情综合| 欧美三级一级片| 国产一区不卡视频| 日韩视频在线观看免费视频| 亚洲一区二区在线免费看| 欧美交换国产一区内射| 日本精品一级二级| 秋霞网一区二区| 日韩视频免费看| 韩国久久久久久| 国产日本一区二区三区| 亚洲国产精品久久久天堂| 久久最新免费视频| 亚洲影视一区| 污污视频网站免费观看| 不卡区在线中文字幕| 午夜av免费看| 亚洲免费在线观看视频| 精品无码黑人又粗又大又长| 欧美日韩亚洲国产综合| 国产精品热久久| 一区二区三区在线播放欧美| 嗯~啊~轻一点视频日本在线观看| 91av免费观看91av精品在线| 吞精囗交69激情欧美| 国产精品10p综合二区| 亚洲成人日韩| 日本不卡一区二区在线观看| 国产精品18久久久久| 无码人妻精品中文字幕| 欧美在线视频你懂得| 牛牛热在线视频| 91av在线播放| 欧美一级全黄| 日韩中文字幕在线视频观看| 成人午夜免费电影| 精品少妇久久久| 精品欧美乱码久久久久久1区2区| 成年人黄视频在线观看| 国内精品久久久久久久| 亚洲国产精品免费视频| 秋霞在线一区二区| 激情五月播播久久久精品| 99成人在线观看| 欧美一级片在线看| 色香蕉在线视频| 国内揄拍国内精品| 久久久久观看| 18禁男女爽爽爽午夜网站免费 | 大胸美女被爆操| 欧美最新大片在线看| аⅴ资源新版在线天堂| 久久99视频免费| 色妞ww精品视频7777| 国内少妇毛片视频| av电影一区二区| 欧日韩不卡视频| 欧美二区三区的天堂| 国产三级在线播放| 高清av免费一区中文字幕| 影音先锋在线一区| 99re久久精品国产| 色婷婷精品大在线视频| www.五月婷婷| 性色av一区二区三区红粉影视| 日韩系列在线| 另类小说第一页| 亚洲蜜臀av乱码久久精品| 亚洲高清视频在线播放| 亚州成人av在线| 欧美亚洲国产精品久久| 精品视频免费在线播放| 久久综合视频网| 在线亚洲欧美日韩| 蜜臀久久99精品久久久无需会员| 超碰97成人| 激情五月五月婷婷| av一区二区三区| 亚洲av综合一区| 日韩精品极品在线观看| 男女在线观看视频| 免费电影一区| 国产在线精品一区二区| 一级片免费网址| 深夜精品寂寞黄网站在线观看| 涩爱av色老久久精品偷偷鲁| 欧美变态另类刺激| 国产精品久久久久久久久免费樱桃 | 国产99在线播放| 老牛影视一区二区三区| 性久久久久久久久久久| 在线看日韩精品电影| 尤物yw193can在线观看| 91久久精品国产91性色| 亚洲激情婷婷| 亚洲精品天堂网| 亚洲黄色有码视频| 高清国产一区二区三区四区五区| 波多野结衣家庭教师视频| 亚洲精品欧美在线| 成人午夜影视| 久久国产精品亚洲va麻豆|