亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

typescript類型體操及關(guān)鍵字使用示例詳解

 更新時(shí)間:2023年11月15日 09:12:24   作者:夕水  
這篇文章主要為大家介紹了typescript類型體操及關(guān)鍵字使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

事情是這樣的,有這樣一道 ts 類型題,代碼如下所示:

type Union = "Mon" | "Tue" | "Wed";
// 補(bǔ)充這里的類型代碼
type Mapping<T extends Union, Value extends string> = any;
type Res = Mapping<Union, "周一" | "周二" | "周三">;
// 以下是輸出結(jié)果
// {
//     mon: "周一";
//     Tue: "周二";
//     Wed: "周三";
// }

觀察題目,其實(shí)就是將兩個(gè)聯(lián)合類型的值組合成接口,其中第一個(gè)聯(lián)合類型的值作為屬性,第二個(gè)聯(lián)合類型的值則作為屬性值,并且兩者的屬性順序是一一對(duì)應(yīng)的。下面跟著我一起來(lái)分析,通過(guò)這道題,我們能理解到 ts 的不少知識(shí)點(diǎn),不信繼續(xù)往下看。

分析

實(shí)際上,在 ts 當(dāng)中,想要保證 ts 的順序是很困難的,這與 ts 編譯器有關(guān),不過(guò)這不影響我們對(duì)這道題的分析,那么這道題如何解決呢?思路就是想辦法將 2 個(gè)聯(lián)合類型構(gòu)造成數(shù)組,然后就可以根據(jù)數(shù)組項(xiàng)一一對(duì)應(yīng)來(lái)轉(zhuǎn)成對(duì)象了,那么這道題的難點(diǎn)在于如何轉(zhuǎn)成數(shù)組。

轉(zhuǎn)成數(shù)組的前提就是我們將聯(lián)合類型的每一項(xiàng)取出來(lái)然后添加到數(shù)組中,那么如何提取呢?下面讓我們一步一步來(lái)實(shí)現(xiàn)。

將并集轉(zhuǎn)成交集

聯(lián)合類型我們也可以叫做并集,如: 1 | 2 | 3,而要實(shí)現(xiàn)添加的第一步,我們需要將并集轉(zhuǎn)成交集,那么如何進(jìn)行交集的轉(zhuǎn)換呢?

其實(shí)我們可以將并集的每一項(xiàng)使用函數(shù)來(lái)推斷,在這里我們需要理解 ts 中的 2 個(gè)關(guān)鍵字用法,如下:

  • extends: 既可以表示類的繼承,也可以表示條件判斷(相當(dāng)于 js 的全等)。
  • infer: 該關(guān)鍵字用于推導(dǎo)某個(gè)類型。

根據(jù)以上分析,我們就可以實(shí)現(xiàn)并集轉(zhuǎn)成交集,代碼如下:

//  X | Y | Z ==> X & Y & Z
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
  k: infer I
) => void
  ? I
  : never;

以上類型就實(shí)現(xiàn)了并集對(duì)交集的轉(zhuǎn)換,理解起來(lái)也很容易,就是判斷給定的泛型參數(shù)是否是任意類型 any,如果是則構(gòu)造成函數(shù)參數(shù)為該類型,然后使用 infer 關(guān)鍵字去推導(dǎo)參數(shù)類型,如果能推導(dǎo)出來(lái),則返回推導(dǎo)出來(lái)的結(jié)果,否則返回 never。

any 與 never 與 void 類型

這個(gè) ts 類型也涉及到了 3 個(gè)類型,即任意類型 any,從不類型 never,和 void 類型。

any 類型

其中 any 用來(lái)表示允許賦值為任意類型。在 ts 中,如果是一個(gè)普通類型,在賦值過(guò)程中改變類型是不被允許的。例如:

let a: string = "123";
a = 2; // error TS2322: Type 'number' is not assignable to type 'string'

以上定義 a 變量的類型是 string,因此修改變量值為數(shù)值,則 ts 編譯會(huì)出錯(cuò),但如果是賦值為任意值類型,則以上操作不會(huì)報(bào)錯(cuò),如下所示:

let a: any = "123";
a = 2; // 允許修改,因?yàn)槭侨我庵殿愋?/pre>

我們也可以訪問(wèn)任意類型的屬性和方法,如下所示:

let b: any = "b";
console.log(b.name); // ts編譯不會(huì)報(bào)錯(cuò)
console.log(b.setName("a")); // ts編譯不會(huì)出錯(cuò)

也就是說(shuō),聲明一個(gè)變量為任意值之后,對(duì)它的任何操作,返回的內(nèi)容的類型都是任意值。

在 ts 中,一個(gè)未聲明類型的變量,也會(huì)被推導(dǎo)成任意類型,如:

let a;
a = "a";
a = 2;
a.setName("b");
// 以上操作在ts中都不會(huì)報(bào)錯(cuò)

never 類型

never 類型表示從不存在的類型,比如一個(gè)函數(shù)拋出異常,它的返回類型就是 never,如:

const fn = (msg: string) => throw new Error(msg); // never

void 類型

void 類型表示沒(méi)有返回值,通常用在沒(méi)有任何返回值的函數(shù)中。如:

const fn = (): void => {
  alert(123);
};

以上類型是包裝成函數(shù)類型推導(dǎo),對(duì)于函數(shù)有沒(méi)有返回值沒(méi)有任何意義,因此這里只需要使用 void 來(lái)代表返回值即可。

將聯(lián)合類型轉(zhuǎn)換成重載函數(shù)類型

下一步,我們就需要將聯(lián)合類型轉(zhuǎn)換成重載函數(shù)類型,例如:

X | Y ==> ((x: X)=>void) & ((y:Y)=>void)

我們要如何實(shí)現(xiàn)呢?其實(shí)就是將泛型參數(shù)包裝成函數(shù)類型,然后再調(diào)用用前面的并集轉(zhuǎn)交集類型,如下:

type UnionToOvlds<U> = UnionToIntersection<
  U extends any ? (f: U) => void : never
>;

做這一步的目的是方便將聯(lián)合類型中的每一項(xiàng)提取出來(lái),因此需要這個(gè)類型,接下來(lái)我們就需要將聯(lián)合類型的每一項(xiàng)取出來(lái),我們叫做 PopUnion 類型。

從聯(lián)合類型中取出每一個(gè)類型

有了前面 2 個(gè)類型的鋪墊,取出聯(lián)合類型中的每一個(gè)類型就很容易,我們只需要包裝成重載函數(shù)類型,然后使用 infer 推斷函數(shù)參數(shù)類型,返回參數(shù)類型即可。代碼如下:

type PopUnion<U> = UnionToOvlds<U> extends (f: infer A) => void ? A : never;

能夠取出聯(lián)合類型的每一個(gè)類型,那么構(gòu)造成數(shù)組就很容易了,不過(guò)接下來(lái)還需要一個(gè)類型,那就是判斷是否是聯(lián)合類型,為此我們需要先實(shí)現(xiàn)這個(gè)類型,即 IsUnion 類型。

判斷是否是聯(lián)合類型

判斷是否是聯(lián)合類型比較簡(jiǎn)單,就是將類型構(gòu)造成一個(gè)數(shù)組,然后使用兩個(gè)數(shù)組比較,不過(guò)我們需要比較的是原始泛型參數(shù)構(gòu)造成數(shù)組和轉(zhuǎn)成交集構(gòu)造成數(shù)組是否相等,相等則返回 false,否則返回 true。代碼如下:

type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;

聯(lián)合類型轉(zhuǎn)數(shù)組

接下來(lái)就是聯(lián)合類型轉(zhuǎn)數(shù)組類型的實(shí)現(xiàn),首先我們需要用到上一節(jié)提到的判斷是否是聯(lián)合類型,如果是聯(lián)合類型,則使用 PopUnion 類型提取聯(lián)合類型的每一項(xiàng),注意這里是需要遞歸的提取剩余項(xiàng)的,直到不是剩余項(xiàng)不是聯(lián)合類型為止,因此這里我們沒(méi)提取一項(xiàng),都需要使用 Exclude 類型將聯(lián)合類型中提取的排除掉,這樣就得到了剩余的聯(lián)合類型,然后我們使用第二個(gè)參數(shù)來(lái)存儲(chǔ)結(jié)果,如果不是聯(lián)合類型就直接添加到數(shù)組中。代碼如下所示:

type UnionToArray<T, A extends unknown[] = []> = IsUnion<T> extends true
  ? UnionToArray<Exclude<T, PopUnion<T>>, [PopUnion<T>, ...A]>
  : [T, ...A];

以上代碼我們使用泛型 A 是一個(gè)未知類型的數(shù)組,并默認(rèn)賦值為空數(shù)組來(lái)存儲(chǔ)結(jié)果,相當(dāng)于我們是從聯(lián)合類型當(dāng)中一項(xiàng)一項(xiàng)的提取出來(lái)然后添加到 A 結(jié)果數(shù)組中,最終返回的結(jié)果就是一個(gè)由聯(lián)合類型每一項(xiàng)組成的數(shù)組。

Exclude 類型

其中 Exclude 類型是 ts 內(nèi)置類型,不過(guò)要實(shí)現(xiàn)還是比較簡(jiǎn)單的,簡(jiǎn)單來(lái)說(shuō)就是如果兩個(gè)參數(shù)相等,則不返回類型,否則返回原類型。代碼如下:

type Exclude<T, U> = T extends U ? never : T;

獲取數(shù)組的長(zhǎng)度

接下來(lái)我們還需要比較兩個(gè)聯(lián)合類型提取出來(lái)的數(shù)組長(zhǎng)度是否相同,為此我們需要先實(shí)現(xiàn)如何獲取一個(gè)數(shù)組類型的長(zhǎng)度,觀察發(fā)現(xiàn)數(shù)組是存在一個(gè) length 屬性的,因此我們可以判斷如果存在 length 屬性,并使用 infer 推斷具體值,能夠推斷出來(lái)就返回這個(gè)推斷的值,否則返回 never,代碼如下:

type Length<T extends ReadonlyArray<any>> = T extends { length: infer L }
  ? L
  : never;

這個(gè)代碼有一個(gè)類型即 ReadonlyArray 類型,它也是 ts 的一個(gè)內(nèi)置類型,表示數(shù)組項(xiàng)只讀的數(shù)組,那么這個(gè)類型是如何實(shí)現(xiàn)的呢?

ReadonlyArray 數(shù)組類型

這個(gè)類型的實(shí)現(xiàn)還是很簡(jiǎn)單的,就是只讀數(shù)組只有一個(gè) at 方法,數(shù)組 at 方法的作用就是獲取一個(gè)整數(shù)值并返回該索引處的項(xiàng)目,允許參數(shù)是正整數(shù)和負(fù)整數(shù),負(fù)整數(shù)從數(shù)組的最后一項(xiàng)開(kāi)始倒數(shù)。因此我們需要先實(shí)現(xiàn)這個(gè)只有 at 方法的接口,代碼如下:

interface RelativeIndexable<T> {
  at(index: number): T | undefined;
}

而只讀數(shù)組類型 ReadonlyArray 只需要繼承這個(gè)接口就行了,代碼如下:

interface ReadonlyArray<T> extends RelativeIndexable<T> {}

實(shí)現(xiàn)比較兩個(gè)數(shù)組長(zhǎng)度的類型

有了能夠獲取數(shù)組長(zhǎng)度的類型,接下來(lái)比較兩個(gè)數(shù)組長(zhǎng)度的類型就很簡(jiǎn)單了,代碼如下:

type CompareLength<
  T extends ReadonlyArray<any>,
  U extends ReadonlyArray<any>
> = Length<T> extends Length<U> ? true : false;

簡(jiǎn)單來(lái)說(shuō),就是兩個(gè)數(shù)組長(zhǎng)度一樣就返回 true,否則返回 false,這也限制了我們最終實(shí)現(xiàn)的類型 2 個(gè)參數(shù)的聯(lián)合類型最終提取出來(lái)的元素一定要一樣。

將屬性構(gòu)造成接口

接下來(lái)我們要實(shí)現(xiàn)將屬性構(gòu)造成接口,要想構(gòu)造成接口,那就需要屬性和屬性值,因此這個(gè)類型的實(shí)現(xiàn)是有 2 個(gè)參數(shù)的,可以看到我們最終實(shí)現(xiàn)的 Mapping 就是有 2 個(gè)參數(shù),第一個(gè)參數(shù)作為屬性,第二個(gè)參數(shù)作為屬性值。而由于接口屬性類型有限制,即只能是 PropertyKey 類型,因此我們是需要判斷的,同理,為了實(shí)現(xiàn)屬性和屬性值一一對(duì)應(yīng)有值的情況下,我們也需要對(duì)第二個(gè)參數(shù)做判斷,只有滿足 2 個(gè)參數(shù)類型都是 PropertyKey 類型,才能構(gòu)造成接口,并且構(gòu)造成接口我們可以使用 Record 類型。

根據(jù)以上分析,我們的最終代碼就實(shí)現(xiàn)如下:

// 不一定要叫Callback,也可以叫名字
type Callback<T, U> = T extends PropertyKey
  ? U extends PropertyKey
    ? Record<T, U>
    : never
  : never;

以上還涉及到了 ts 的兩個(gè)內(nèi)置類型,第一個(gè)是 PropertyKey 類型,第二個(gè)則是Record<T,U>類型,下面我們來(lái)一一看下這 2 個(gè)類型的實(shí)現(xiàn)。

PropertyKey 類型

第一個(gè) PropertyKey 類型非常簡(jiǎn)單,它表示對(duì)象的屬性類型,我們只需要知道 js 對(duì)象的屬性只能是字符串或者數(shù)字或者符號(hào)就可以知道這個(gè)類型的實(shí)現(xiàn),代碼如下:

type PropertyKey = string | number | symbol;

可以看到這就是一個(gè)聯(lián)合類型,屬性的類型只能是字符串或者數(shù)值或者符號(hào)。

Record 類型

Record 類型表示構(gòu)造一個(gè)構(gòu)造一個(gè)具有類型 T 的一組屬性 U 的類型,我們只需要使用 in 操作符即可實(shí)現(xiàn),因?yàn)檫@個(gè)類型的第一個(gè)參數(shù)是要作為接口屬性的,而第二個(gè)參數(shù)則是作為對(duì)應(yīng)的屬性值。代碼如下:

type Record<T extends keyof any, U> = {
  [K in T]: U;
};

這就是 Record 類型的實(shí)現(xiàn),這其中還設(shè)計(jì)到了 ts 的一個(gè)關(guān)鍵字,即 keyof,它表示提取類型的屬性,這個(gè)關(guān)鍵字通常用來(lái)提取接口的屬性,最后會(huì)返回組成屬性的聯(lián)合類型。例如:

type Test = {
  a: string;
  1: number;
};
type TestKey = keyof Test; // 'a' | 1

將兩個(gè)數(shù)組類型構(gòu)造成接口

有了前面的幾個(gè)類型的實(shí)現(xiàn),接下來(lái)我們需要實(shí)現(xiàn)一個(gè)根據(jù) 2 個(gè)參數(shù)數(shù)組構(gòu)造成接口的類型,為此我們需要定義第三個(gè)參數(shù),第三個(gè)參數(shù)應(yīng)該是一個(gè)接口對(duì)象,用來(lái)當(dāng)作最終返回的結(jié)果,默認(rèn)是一個(gè)空對(duì)象,而前面 2 個(gè)參數(shù)就是我們的屬性組成的只讀數(shù)組。結(jié)構(gòu)如下所示:

type Zip<
  T extends ReadonlyArray<any>,
  U extends ReadonlyArray<any>,
  R extends Record<string, any> = {}
> = any;

接下來(lái)第一步,首先我們需要比較 2 個(gè)參數(shù)數(shù)組長(zhǎng)度應(yīng)該是一樣的,不一樣,我們就直接返回 never。如下所示:

type Zip<
  T extends ReadonlyArray<any>,
  U extends ReadonlyArray<any>,
  R extends Record<string, any> = {}
> = CompareLength<T, U> extends true ? any : never;
ps: 以上包括后面用 any 表示我們還沒(méi)有實(shí)現(xiàn),起一個(gè)占位符作用,方便我們理解實(shí)現(xiàn)思路。

緊接著第二步,我們需要判斷是否是空數(shù)組,只需要判斷其中一個(gè)即可,因?yàn)槲覀円呀?jīng)判斷了兩個(gè)數(shù)組長(zhǎng)度是否相等,如果其中一個(gè)是空數(shù)組,那么另一個(gè)必定也是空數(shù)組,如果是空數(shù)組,直接返回結(jié)果即可,此時(shí)默認(rèn)值就是空對(duì)象,直接返回結(jié)果也合理,代碼如下:

type Zip<
  T extends ReadonlyArray<any>,
  U extends ReadonlyArray<any>,
  R extends Record<string, any> = {}
> = CompareLength<T, U> extends true ? (T extends [] ? R : any) : never;

接下來(lái)第三步,我們還需要做判斷,那就是如果 2 個(gè)數(shù)組都只有一個(gè)數(shù)組項(xiàng),那么我們只需要將第一個(gè)數(shù)組項(xiàng)提取出來(lái),這里當(dāng)然是使用 infer 關(guān)鍵字來(lái)推導(dǎo)數(shù)組項(xiàng),然后使用 Callback 類型構(gòu)造成接口并與 R 結(jié)果取并集即可。代碼如下所示:

type Zip<
  T extends ReadonlyArray<any>,
  U extends ReadonlyArray<any>,
  R extends Record<string, any> = {}
> = CompareLength<T, U> extends true
  ? T extends []
    ? R
    : T extends [infer F1]
    ? U extends [infer F2]
      ? R & Callback<F1, F2>
      : never
    : any
  : never;

第四步就是如果數(shù)組有多個(gè)數(shù)組項(xiàng),則我們需要遞歸的取并集。代碼如下所示:

type Zip<
  T extends ReadonlyArray<any>,
  U extends ReadonlyArray<any>,
  R extends Record<string, any> = {}
> = CompareLength<T, U> extends true
  ? T extends []
    ? R
    : T extends [infer F1]
    ? U extends [infer F2]
      ? R & Callback<F1, F2>
      : never
    : T extends [infer F1, ...infer T1]
    ? U extends [infer F2, ...infer T2]
      ? Zip<T1, T2, R & Callback<F1, F2>>
      : never
    : never
  : never;

雖然這個(gè)類型的實(shí)現(xiàn)代碼比較長(zhǎng),但其實(shí)我們逐一拆分下來(lái)理解起來(lái)還是比較容易的。

實(shí)現(xiàn) Mapping 類型

有了前面幾個(gè)類型的實(shí)現(xiàn),最終我們就可以解答這道題了,我們只需要將 2 個(gè)聯(lián)合類型構(gòu)造成 2 個(gè)數(shù)組,然后使用 Zip 類型將 2 個(gè)類型組成的數(shù)組轉(zhuǎn)成接口即可,代碼如下:

type Mapping<T extends Union, Value extends string> = Zip<
  UnionToArray<T>,
  UnionToArray<Value>
>;

以上代碼很好理解,我們將 2 個(gè)聯(lián)合類型使用 UnionToArray 構(gòu)造成 2 個(gè)類型數(shù)組,然后使用 Zip 類型構(gòu)造成接口。

優(yōu)化

不過(guò)以上代碼的實(shí)現(xiàn)還不算完美,因?yàn)槲覀冏罱K的結(jié)果是使用 Record 類型展示的,并不直觀,因此最后一步,我們還需要將 Record 類型轉(zhuǎn)成可以直觀看到的接口類型,很簡(jiǎn)單,只需要讀取每一個(gè)接口屬性即可,和 Record 類型實(shí)現(xiàn)原理很類似。代碼如下:

type ToObj<T> = {
  [K in keyof T]: T[K];
};

最終實(shí)現(xiàn)版本

將優(yōu)化后的代碼與前面的實(shí)現(xiàn)合并,就得到了我們的最終實(shí)現(xiàn),代碼如下:

type Mapping<T extends Union, Value extends string> = ToObj<
  Zip<UnionToArray<T>, UnionToArray<Value>>
>;

下面,我們將以上所有實(shí)現(xiàn)代碼整理到一起,代碼如下:

// 第一步
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
  k: infer I
) => void
  ? I
  : never;
// 第二步
type UnionToOvlds<U> = UnionToIntersection<
  U extends any ? (f: U) => void : never
>;
// 第三步
type PopUnion<U> = UnionToOvlds<U> extends (f: infer A) => void ? A : never;
// 第四步
type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
// 第五步
type UnionToArray<T, A extends unknown[] = []> = IsUnion<T> extends true
  ? UnionToArray<Exclude<T, PopUnion<T>>, [PopUnion<T>, ...A]>
  : [T, ...A];
// 第六步
type Length<T extends ReadonlyArray<any>> = T extends { length: infer L }
  ? L
  : never;
// 第七步
type CompareLength<
  T extends ReadonlyArray<any>,
  U extends ReadonlyArray<any>
> = Length<T> extends Length<U> ? true : false;
// 第八步
type Callback<T, U> = T extends PropertyKey
  ? U extends PropertyKey
    ? Record<T, U>
    : never
  : never;
// 第九步
type Zip<
  T extends ReadonlyArray<any>,
  U extends ReadonlyArray<any>,
  R extends Record<string, any> = {}
> = CompareLength<T, U> extends true
  ? T extends []
    ? R
    : T extends [infer F1]
    ? U extends [infer F2]
      ? R & Callback<F1, F2>
      : never
    : T extends [infer F1, ...infer T1]
    ? U extends [infer F2, ...infer T2]
      ? Zip<T1, T2, R & Callback<F1, F2>>
      : never
    : never
  : never;
// 第十步
type ToObj<T> = {
  [K in keyof T]: T[K];
};
// 最終
type Mapping<T extends Union, Value extends string> = ToObj<
  Zip<UnionToArray<T>, UnionToArray<Value>>
>;

總結(jié)

下面我們來(lái)總結(jié)一下這道題中我們學(xué)到的知識(shí)點(diǎn):

  • extends 關(guān)鍵字用于條件判斷。
  • infer 關(guān)鍵字用于推導(dǎo)類型。
  • keyof 關(guān)鍵字用于獲取對(duì)象接口屬性。
  • ts 類型遞歸。
  • ts 中的 3 個(gè)基本類型的含義,即 any,never,void 的含義。
  • ts 中內(nèi)置類型的實(shí)現(xiàn),如: ReadonlyArray,Exclude,PropertyKey,Record。

以上的知識(shí)點(diǎn),在 ts 類型體操當(dāng)中將會(huì)經(jīng)常用到,所以需要理解深刻。

只是一道題目,我們就學(xué)到了 ts 的很多類型體操的知識(shí),ts 類型這么有趣,難道不是嗎?

更多關(guān)于typescript類型體操的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • TypeScript 基本數(shù)據(jù)類型實(shí)例詳解

    TypeScript 基本數(shù)據(jù)類型實(shí)例詳解

    這篇文章主要為大家介紹了TypeScript 基本數(shù)據(jù)類型實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • 數(shù)據(jù)結(jié)構(gòu)TypeScript之鏈表實(shí)現(xiàn)詳解

    數(shù)據(jù)結(jié)構(gòu)TypeScript之鏈表實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了數(shù)據(jù)結(jié)構(gòu)TypeScript之鏈表實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • 鮮為人知的JavaScript5個(gè)JSON秘密功能

    鮮為人知的JavaScript5個(gè)JSON秘密功能

    這篇文章主要為大家介紹了鮮為人知的JavaScript中5個(gè)JSON秘密功能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • CesiumJS源碼雜談之從光到?Uniform

    CesiumJS源碼雜談之從光到?Uniform

    這篇文章主要為大家介紹了CesiumJS源碼雜談之從光到Uniform的使用示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 數(shù)據(jù)結(jié)構(gòu)TypeScript之棧和隊(duì)列詳解

    數(shù)據(jù)結(jié)構(gòu)TypeScript之棧和隊(duì)列詳解

    這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu)TypeScript之棧和隊(duì)列詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • TS中Array.reduce提示沒(méi)有與此調(diào)用匹配的重載解析

    TS中Array.reduce提示沒(méi)有與此調(diào)用匹配的重載解析

    這篇文章主要為大家介紹了TS中Array.reduce提示沒(méi)有與此調(diào)用匹配的重載解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • TypeScript 高級(jí)數(shù)據(jù)類型實(shí)例詳解

    TypeScript 高級(jí)數(shù)據(jù)類型實(shí)例詳解

    這篇文章主要為大家介紹了TypeScript 高級(jí)數(shù)據(jù)類型實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • js庫(kù)Modernizr的介紹和使用

    js庫(kù)Modernizr的介紹和使用

    Modernizr是一個(gè)開(kāi)源的JS庫(kù),它使得那些基于訪客瀏覽器的不同(指對(duì)新標(biāo)準(zhǔn)支持性的差異)而開(kāi)發(fā)不同級(jí)別體驗(yàn)的設(shè)計(jì)師的工作變得更為簡(jiǎn)單
    2015-05-05
  • 前端輕量級(jí)MVC框架CanJS詳解

    前端輕量級(jí)MVC框架CanJS詳解

    你可能聽(tīng)說(shuō)了這個(gè)新MVC框架: CanJS。還有什么比用它來(lái)創(chuàng)建一個(gè)聯(lián)系人Web App更能深入了解它的辦法呢?當(dāng)看完這篇教程,你將全面了解用它的什么工具來(lái)創(chuàng)建你自己的Web App。
    2014-09-09
  • 移動(dòng)設(shè)備web開(kāi)發(fā)首選框架:zeptojs介紹

    移動(dòng)設(shè)備web開(kāi)發(fā)首選框架:zeptojs介紹

    這篇文章主要介紹了移動(dòng)設(shè)備web開(kāi)發(fā)首選框架:zeptojs介紹,他兼容jquery的API,所以學(xué)起來(lái)或用起來(lái)并不吃力,需要的朋友可以參考下
    2015-01-01

最新評(píng)論