日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁(yè) > 科技  > 軟件

解鎖TypeScript的潛力:改進(jìn)標(biāo)準(zhǔn)庫(kù)類型

來(lái)源: 責(zé)編: 時(shí)間:2023-08-20 23:17:07 607觀看
導(dǎo)讀在 TypeScript 項(xiàng)目中,我們的編寫代碼并不是唯一的代碼。標(biāo)準(zhǔn)庫(kù)和運(yùn)行環(huán)境也會(huì)參與類型檢查。這些包括在全局范圍內(nèi)可用的JavaScript方法和Web平臺(tái)API,包括用于處理數(shù)組、window對(duì)象、Fetch API等方法。本文將探討TypeS

8Il28資訊網(wǎng)——每日最新資訊28at.com

在 TypeScript 項(xiàng)目中,我們的編寫代碼并不是唯一的代碼。標(biāo)準(zhǔn)庫(kù)和運(yùn)行環(huán)境也會(huì)參與類型檢查。這些包括在全局范圍內(nèi)可用的JavaScript方法和Web平臺(tái)API,包括用于處理數(shù)組、window對(duì)象、Fetch API等方法。本文將探討TypeScript標(biāo)準(zhǔn)庫(kù)最常見的問(wèn)題以及編寫更安全、可靠的代碼的方法!8Il28資訊網(wǎng)——每日最新資訊28at.com

1、TypeScript 標(biāo)準(zhǔn)庫(kù)的問(wèn)題

Summer IS HERE

TypeScript的標(biāo)準(zhǔn)庫(kù)在很大程度上提供了高質(zhì)量的類型定義,但是一些廣泛使用的 API 的類型聲明可能過(guò)于寬松或過(guò)于嚴(yán)格8Il28資訊網(wǎng)——每日最新資訊28at.com

過(guò)于寬松類型的最常見問(wèn)題是使用 any 而不是更精確的類型,比如 unknown。在標(biāo)準(zhǔn)庫(kù)中,F(xiàn)etch API 是導(dǎo)致類型安全問(wèn)題最常見的來(lái)源。json()方法返回的是 any 類型的值,這可能導(dǎo)致運(yùn)行時(shí)錯(cuò)誤和類型不匹配,同樣的情況也適用于JSON.parse方法。8Il28資訊網(wǎng)——每日最新資訊28at.com

async function fetchPokemons() {  const response = await fetch('https://pokeapi.co/api/v2/pokemon');  const data = await response.json();  return data;}const pokemons = await fetchPokemons();//    ^?  anypokemons.data.map(pokemon => pokemon.name);//            ^  TypeError: Cannot read properties of undefined

另一方面,有一些API的類型聲明過(guò)于限制,可能導(dǎo)致開發(fā)體驗(yàn)較差。例如,Array.filter方法的工作方式與直覺相反,需要手動(dòng)進(jìn)行類型轉(zhuǎn)換或編寫類型保護(hù)。8Il28資訊網(wǎng)——每日最新資訊28at.com

// filteredArray 的類型是 Array<number | undefined>。const filteredArray = [1, 2, undefined].filter(Boolean);// filteredArray的類型是 Array<number>const filteredArray = [1, 2, undefined].filter(  (item): item is number => Boolean(item));

沒有簡(jiǎn)單的方法來(lái)升級(jí)或替換標(biāo)準(zhǔn)庫(kù)的類型聲明,因?yàn)樗念愋投x是隨 TypeScript 編譯器一起提供的。然而,如果想充分利用 TypeScript,有多種方法可以解決這個(gè)問(wèn)題。8Il28資訊網(wǎng)——每日最新資訊28at.com

下面來(lái)以 Fetch API 為例探討一些選項(xiàng)。8Il28資訊網(wǎng)——每日最新資訊28at.com

2、使用類型斷言

Summer IS HERE

一個(gè)快速解決方案是手動(dòng)指定類型。為了做到這一點(diǎn),需要描述響應(yīng)的格式并將any類型轉(zhuǎn)換為所需的類型。這樣就可以將對(duì)any的使用限制在代碼庫(kù)的一小部分中,比在整個(gè)程序中都使用返回的any類型要好很多。8Il28資訊網(wǎng)——每日最新資訊28at.com

interface PokemonListResponse {  count: number;  next: string | null;  previous: string | null;  results: Pokemon[];}interface Pokemon {  name: string;  url: string;}async function fetchPokemons() {  const response = await fetch('https://pokeapi.co/api/v2/pokemon');  const data = await response.json() as PokemonListResponse;  return data;}const pokemons = await fetchPokemons();//    ^?  PokemonListResponse

另外,TypeScript 現(xiàn)在將會(huì)突出顯示對(duì)不存在字段的訪問(wèn)的錯(cuò)誤。然而,類型轉(zhuǎn)換給我們帶來(lái)了額外的責(zé)任,即準(zhǔn)確描述從服務(wù)端返回的類型。8Il28資訊網(wǎng)——每日最新資訊28at.com

pokemons.data.map(pokemon => pokemon.name);//       ^  Error: “Pokemon List Response”類型中不存在屬性“data”//          應(yīng)該在這里使用 'results' 字段

類型斷言可能存在風(fēng)險(xiǎn),應(yīng)謹(jǐn)慎使用。如果斷言不正確,可能會(huì)導(dǎo)致意外行為。例如,在描述類型時(shí)容易犯錯(cuò),比如忽略字段可能為null或undefined的情況。8Il28資訊網(wǎng)——每日最新資訊28at.com

3、使用類型保護(hù)

Summer IS HERE

我們可以通過(guò)首先將any強(qiáng)制轉(zhuǎn)換為unknown來(lái)增強(qiáng)上述解決方案。這清楚地表明 fetch 函數(shù)可以返回任何類型的數(shù)據(jù)。然后需要通過(guò)編寫類型保護(hù)來(lái)驗(yàn)證響應(yīng)是否具有需要的數(shù)據(jù),如下所示:8Il28資訊網(wǎng)——每日最新資訊28at.com

function isPokemonListResponse(data: unknown): data is PokemonListResponse {    if (typeof data !== 'object' || data === null) return false;    if (typeof data.count !== 'number') return false;    if (data.next !== null && typeof data.next !== 'string') return false;    if (data.previous !== null && typeof data.previous !== 'string') return false;    if (!Array.isArray(data.results)) return false;    for (const pokemon of data.results) {        if (typeof pokemon.name !== 'string') return false;        if (typeof pokemon.url !== 'string') return false;    }    return true;}

類型守衛(wèi)函數(shù)接收一個(gè)具有unknown類型的變量作為輸入。使用is操作符來(lái)指定輸出類型,表示已經(jīng)檢查了data變量中的數(shù)據(jù),并且它具有這種類型。在函數(shù)內(nèi)部,編寫所有必要的檢查,以驗(yàn)證需要的所有字段。8Il28資訊網(wǎng)——每日最新資訊28at.com

可以使用得到的類型守衛(wèi)來(lái)將unknown類型縮小到想要處理的類型。這樣,如果響應(yīng)數(shù)據(jù)格式發(fā)生變化,可以迅速檢測(cè)到并在應(yīng)用邏輯中處理該情況。8Il28資訊網(wǎng)——每日最新資訊28at.com

async function fetchPokemons() {    const response = await fetch('https://pokeapi.co/api/v2/pokemon');    const data = (await response.json()) as unknown;    if (!isPokemonListResponse(data)) {        throw new Error('error');    }    return data;}const pokemons = await fetchPokemons();//    ^?  PokemonListResponse

然而,編寫類型守衛(wèi)可能會(huì)很繁瑣,特別是在處理大量數(shù)據(jù)時(shí)。此外,在類型守衛(wèi)中犯錯(cuò)的風(fēng)險(xiǎn)很高,這等同于在類型定義本身上犯錯(cuò)。8Il28資訊網(wǎng)——每日最新資訊28at.com

4、使用 Zod 庫(kù)

Summer IS HERE

為了簡(jiǎn)化類型保護(hù)的編寫,可以使用 Zod 等數(shù)據(jù)驗(yàn)證庫(kù)。使用 Zod,可以定義一個(gè)數(shù)據(jù)模式,然后調(diào)用一個(gè)函數(shù)來(lái)根據(jù)該模式檢查數(shù)據(jù)格式。8Il28資訊網(wǎng)——每日最新資訊28at.com

import { z } from 'zod';const schema = z.object({    count: z.number(),    next: z.string().nullable(),    previous: z.string().nullable(),    results: z.array(        z.object({            name: z.string(),            url: z.string(),        })    ),});

這類庫(kù)最初是以TypeScript為目標(biāo)開發(fā)的。它們?cè)试S我們只需一次描述數(shù)據(jù)模式,然后自動(dòng)生成類型定義。這消除了手動(dòng)編寫TypeScript接口的需要,并避免了重復(fù)工作。8Il28資訊網(wǎng)——每日最新資訊28at.com

type PokemonListResponse = z.infer<typeof schema>;

這個(gè)函數(shù)本質(zhì)上就像一個(gè)類型守衛(wèi),而我們無(wú)需手動(dòng)編寫它。8Il28資訊網(wǎng)——每日最新資訊28at.com

async function fetchPokemons() {    const response = await fetch('https://pokeapi.co/api/v2/pokemon');    const data = (await response.json()) as unknown;    return schema.parse(data);}const pokemons = await fetchPokemons();//    ^?  PokemonListResponse

因此,我們得到了一種可靠的解決方案,不留下任何犯錯(cuò)的機(jī)會(huì)。由于不再手動(dòng)編寫類型定義,因此無(wú)法出現(xiàn)類型定義的錯(cuò)誤。類型守衛(wèi)也不會(huì)出現(xiàn)錯(cuò)誤。模式中可能會(huì)出現(xiàn)錯(cuò)誤,但可以在開發(fā)過(guò)程中察覺到這些錯(cuò)誤。8Il28資訊網(wǎng)——每日最新資訊28at.com

5、Zod 的替代品

Summer IS HERE

Zod有許多不同的替代品,它們?cè)诠δ堋⒗壌笮『托阅苌嫌兴鶇^(qū)別。對(duì)于每個(gè)應(yīng)用程序,您可以選擇最合適的選項(xiàng)。8Il28資訊網(wǎng)——每日最新資訊28at.com

例如,superstruct 庫(kù)是Zod的一個(gè)更輕量級(jí)的替代方案。由于該庫(kù)相對(duì)較小(13.1 kB 對(duì)比 3.4 kB),因此更適合在客戶端使用。8Il28資訊網(wǎng)——每日最新資訊28at.com

typia 庫(kù)是一種稍微不同的方法,它采用提前編譯的方式。由于編譯階段,數(shù)據(jù)驗(yàn)證的速度更快。這對(duì)于大量數(shù)據(jù)或服務(wù)端重型代碼特別重要。8Il28資訊網(wǎng)——每日最新資訊28at.com

6、解決根本問(wèn)題

Summer IS HERE

使用 Zod 等庫(kù)進(jìn)行數(shù)據(jù)驗(yàn)證可以幫助克服 TypeScript 標(biāo)準(zhǔn)庫(kù)中任何類型的問(wèn)題。但是,了解返回 any 的標(biāo)準(zhǔn)庫(kù)方法仍然很重要,并在使用這些方法時(shí)將這些類型替換為unknown。8Il28資訊網(wǎng)——每日最新資訊28at.com

理想情況下,標(biāo)準(zhǔn)庫(kù)應(yīng)該使用unknown類型而不是any。這將使編譯器能夠建議所有需要類型保護(hù)的地方。幸運(yùn)的是,TypeScript 的聲明合并功能提供了這種可能性。8Il28資訊網(wǎng)——每日最新資訊28at.com

在 TypeScript 中,接口有一個(gè)有用的功能,即同名接口的多個(gè)聲明將合并為一個(gè)聲明。例如,如果有一個(gè)帶有name字段的 User 接口,然后聲明另一個(gè)帶有age字段的 User 接口,則生成的 User 接口將同時(shí)具有name和age字段。8Il28資訊網(wǎng)——每日最新資訊28at.com

interface User {    name: string;}interface User {    age: number;}const user: User = {    name: 'CUGGZ',    age: 25,};

這個(gè)特性不僅在單個(gè)文件內(nèi)有效,而是在整個(gè)項(xiàng)目范圍內(nèi)全局有效。這意味著可以使用這個(gè)特性來(lái)擴(kuò)展 Window 類型,甚至是擴(kuò)展外部庫(kù)的類型,包括標(biāo)準(zhǔn)庫(kù)。8Il28資訊網(wǎng)——每日最新資訊28at.com

declare global {    interface Window {        sayHello: () => void;    }}window.sayHello();//     ^  TypeScript 現(xiàn)在知道這個(gè)方法了

通過(guò)使用聲明合并,可以完全解決TypeScript標(biāo)準(zhǔn)庫(kù)中 any 類型的問(wèn)題。8Il28資訊網(wǎng)——每日最新資訊28at.com

7、Fetch API 更好的類型

Summer IS HERE

為了改進(jìn)標(biāo)準(zhǔn)庫(kù)中的 Fetch API,需要更正 json() 方法的類型,以便它始終返回 unknown 而不是any。首先,確定json方法是 Response 接口的一部分。8Il28資訊網(wǎng)——每日最新資訊28at.com

interface Response extends Body {    readonly headers: Headers;    readonly ok: boolean;    readonly redirected: boolean;    readonly status: number;    readonly statusText: string;    readonly type: ResponseType;    readonly url: string;    clone(): Response;}

在Response的方法中找不到j(luò)son()方法。相反,可以看到 Response 接口繼承自 Body 接口。因此,查看 Body 接口以找到需要的方法。可以看到,json()方法實(shí)際上返回any類型。8Il28資訊網(wǎng)——每日最新資訊28at.com

interface Body {    readonly body: ReadableStream<Uint8Array> | null;    readonly bodyUsed: boolean;    arrayBuffer(): Promise<ArrayBuffer>;    blob(): Promise<Blob>;    formData(): Promise<FormData>;    text(): Promise<string>;    json(): Promise<any>;}

為了解決這個(gè)問(wèn)題,可以在項(xiàng)目中再定義一次 Body 接口,如下所示:8Il28資訊網(wǎng)——每日最新資訊28at.com

declare global {    interface Body {        json(): Promise<unknown>;    }}

由于聲明合并, json()方法現(xiàn)在將始終返回 unknown 類型。8Il28資訊網(wǎng)——每日最新資訊28at.com

async function fetchPokemons() {    const response = await fetch('https://pokeapi.co/api/v2/pokemon');    const data = await response.json();    //    ^?  unknown    return data;}

8、JSON.parse 更好的類型

Summer IS HERE

同樣,我們可以修復(fù)JSON解析的問(wèn)題。默認(rèn)情況下,parse()方法返回any類型,這可能會(huì)在使用解析后的數(shù)據(jù)時(shí)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。8Il28資訊網(wǎng)——每日最新資訊28at.com

const data = JSON.parse(text);//    ^?  any

為了解決這個(gè)問(wèn)題,我們需要知道 parse() 方法是 JSON 接口的一部分。然后可以在項(xiàng)目中聲明類型,如下所示:8Il28資訊網(wǎng)——每日最新資訊28at.com

declare global {    interface JSON {        parse(            text: string,             reviver?: (this: any, key: string, value: any) => any        ): unknown;    }}

現(xiàn)在,JSON 解析總是返回unknow類型,這可以帶來(lái)更安全、更易于維護(hù)的代碼庫(kù)。8Il28資訊網(wǎng)——每日最新資訊28at.com

const data = JSON.parse(text);//    ^?  unknown

9、Array.isArray 更好的類型

Summer IS HERE

另一個(gè)常見的例子是檢查變量是否是數(shù)組。默認(rèn)情況下,此方法返回包含any類型的數(shù)組,基本上與使用any沒有區(qū)別。8Il28資訊網(wǎng)——每日最新資訊28at.com

if (Array.isArray(userInput)) {    console.log(userInput);    //          ^?  any[]}

這里可以擴(kuò)展數(shù)組構(gòu)造函數(shù)的類型,如下所示,該方法現(xiàn)在返回一個(gè)包含unknown類型的數(shù)組,這樣更安全和準(zhǔn)確。8Il28資訊網(wǎng)——每日最新資訊28at.com

declare global {    interface ArrayConstructor {        isArray(arg: any): arg is unknown[];    }}if (Array.isArray(userInput)) {    console.log(userInput);    //          ^?  unknown[]}

10、structuredClone 更好的類型

Summer IS HERE

最近引入的克隆對(duì)象方法 structuredClone 也返回 any。8Il28資訊網(wǎng)——每日最新資訊28at.com

const user = {    name: 'John',    age: 30,};const copy = structuredClone(user);//    ^?  any

修復(fù)這個(gè)問(wèn)題和前面的方法一樣。不過(guò),在這種情況下,需要添加一個(gè)新的函數(shù)簽名而不是擴(kuò)展接口。幸運(yùn)的是,聲明合并對(duì)函數(shù)也同樣適用。因此,可以按照以下方式修復(fù)這個(gè)問(wèn)題:8Il28資訊網(wǎng)——每日最新資訊28at.com

declare global {    declare function structuredClone<T>(value: T, options?: StructuredSerializeOptions): T;}

現(xiàn)在克隆的對(duì)象將具有與原始對(duì)象具有相同的類型。8Il28資訊網(wǎng)——每日最新資訊28at.com

const user = {    name: 'John',    age: 30,};const copy = structuredClone(user);//    ^?  { name: string, age: number }

11、Array.filter 更好的類型

Summer IS HERE

聲明合并不僅對(duì)修復(fù)any類型的問(wèn)題很有用,還可以改進(jìn)標(biāo)準(zhǔn)庫(kù)的易用性。下面來(lái)看一下Array.filter方法的例子。8Il28資訊網(wǎng)——每日最新資訊28at.com

const filteredArray = [1, 2, undefined].filter(Boolean);//    ^?  Array<number | undefined>

可以讓 TypeScript 在應(yīng)用 Boolean 過(guò)濾函數(shù)后自動(dòng)縮小數(shù)組類型。為此,需要擴(kuò)展 Array 接口,如下所示:8Il28資訊網(wǎng)——每日最新資訊28at.com

type NonFalsy<T> = T extends false | 0 | "" | null | undefined | 0n ? never : T;declare global {    interface Array<T> {      filter(predicate: BooleanConstructor, thisArg?: any): Array<NonFalsy<T>>;    }}

現(xiàn)在可以使用filter的簡(jiǎn)寫形式,并獲得正確的數(shù)據(jù)類型作為結(jié)果。8Il28資訊網(wǎng)——每日最新資訊28at.com

12、ts-reset

Summer IS HERE

TypeScript 的標(biāo)準(zhǔn)庫(kù)包含超過(guò) 1000 個(gè) any 類型的實(shí)例。在使用嚴(yán)格類型的代碼時(shí),有很多地方可以改善開發(fā)體驗(yàn)。避免手動(dòng)修復(fù)標(biāo)準(zhǔn)庫(kù)的一種解決方案是使用 ts-reset 庫(kù)。它易于使用,只需在項(xiàng)目中導(dǎo)入一次。8Il28資訊網(wǎng)——每日最新資訊28at.com

import "@total-typescript/ts-reset";

該庫(kù)相對(duì)較新,因此它對(duì)標(biāo)準(zhǔn)庫(kù)的修復(fù)還沒有想要的那么多。然而,我相信這只是一個(gè)開始。值得注意的是,ts-reset 僅包含對(duì)全局類型的安全更改,不會(huì)導(dǎo)致潛在的運(yùn)行時(shí)錯(cuò)誤。8Il28資訊網(wǎng)——每日最新資訊28at.com

13、避免在庫(kù)中使用

Summer IS HERE

改進(jìn) TypeScript 的標(biāo)準(zhǔn)庫(kù)有很多好處。然而,值得注意的是,重新定義標(biāo)準(zhǔn)庫(kù)的全局類型限制了這種方法僅適用于應(yīng)用。不適用于庫(kù),因?yàn)槭褂眠@樣的庫(kù)會(huì)意外地改變應(yīng)用的全局類型的行為。8Il28資訊網(wǎng)——每日最新資訊28at.com

一般來(lái)說(shuō),建議避免在庫(kù)中修改 TypeScript 的標(biāo)準(zhǔn)庫(kù)類型。相反,可以使用靜態(tài)分析工具在代碼質(zhì)量和類型安全方面獲得類似的結(jié)果,這適用于庫(kù)開發(fā)。8Il28資訊網(wǎng)——每日最新資訊28at.com

14、總結(jié)

Summer IS HERE

TypeScript的標(biāo)準(zhǔn)庫(kù)是TypeScript編譯器的一個(gè)關(guān)鍵組成部分,提供了一系列內(nèi)置類型,用于處理JavaScript和Web平臺(tái)API。然而,標(biāo)準(zhǔn)庫(kù)并不完美,其中一些類型聲明存在問(wèn)題,可能導(dǎo)致代碼中的類型檢查質(zhì)量較低。本文探討了一些TypeScript標(biāo)準(zhǔn)庫(kù)常見的問(wèn)題以及編寫更安全、更可靠的代碼的方法。8Il28資訊網(wǎng)——每日最新資訊28at.com

通過(guò)使用類型斷言、類型守衛(wèi)和類似Zod的庫(kù),可以改善代碼庫(kù)的類型安全性和代碼質(zhì)量。此外,還可以通過(guò)使用聲明合并來(lái)修復(fù)問(wèn)題的根本,從而改善TypeScript標(biāo)準(zhǔn)庫(kù)的類型安全性和人性化程度。8Il28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-6177-0.html解鎖TypeScript的潛力:改進(jìn)標(biāo)準(zhǔn)庫(kù)類型

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 三言兩語(yǔ)說(shuō)透設(shè)計(jì)模式的藝術(shù)-適配器模式

下一篇: 最新技術(shù)趨勢(shì):RabbitMQ在云原生應(yīng)用中的應(yīng)用

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 主站蜘蛛池模板: 民丰县| 北海市| 根河市| 汤原县| 南溪县| 台山市| 长兴县| 台南县| 岳西县| 抚松县| 和政县| 佛山市| 依兰县| 浦北县| 沙湾县| 阳原县| 深圳市| 九龙城区| 万宁市| 云南省| 隆化县| 辽阳县| 闽侯县| 晋江市| 象山县| 灵璧县| 黄大仙区| 阿拉尔市| 中山市| 遂平县| 山东省| 抚州市| 塔城市| 海阳市| 尚义县| 伊宁市| 永和县| 博白县| 环江| 恭城| 台安县|