欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

typescript?type類(lèi)型使用梳理總結(jié)

 更新時(shí)間:2023年08月18日 10:38:23   作者:goblin_pitcher  
這篇文章主要為大家介紹了typescript?type類(lèi)型使用梳理總結(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

倉(cāng)庫(kù)地址:https://github.com/goblin-pitcher/steel-wheel-run/blob/master/typescript/type-challenge-pre-content.md

最近準(zhǔn)備開(kāi)始刷type-challenges,因此先梳理一下ts類(lèi)型相關(guān)知識(shí)點(diǎn)。

遺漏知識(shí)點(diǎn)總結(jié)

ts的type符合圖靈完備。這意味著ts類(lèi)型包含循環(huán)、判斷等一系列基本操作。

類(lèi)型集合

類(lèi)型應(yīng)當(dāng)作集合來(lái)看,其中:

unknown是全集,包含所有類(lèi)型,是所有類(lèi)型的父級(jí)

之前在泛型中會(huì)寫(xiě)Comp<T extends unknown>看來(lái)是有些多此一舉了...

never是空集,是所有類(lèi)型的子集

ts的設(shè)計(jì)符合里氏替換原則,即子集可以替換所有父級(jí),這意味著:

interface Parent {
  id: string;
}
// 符合里氏替換原則,不會(huì)報(bào)錯(cuò)
interface Child extends Parent {
  id: "childIdA"|"childIdB"; // "childIdA"|"childIdB"是string的子集
  key: number; // Parent中沒(méi)有key,該屬性是Parent的拓展
}
// 不符合里氏替換原則,報(bào)錯(cuò)
interface ChildError extends Parent {
  id: number; // number不是string的子集
}
type A = {a: string};
type B = {a: "A"|"a", b: number};
let a: A = {a: "xxx"};
let b: B = {a: "a", b: 2};
// 符合B是A的子集,該賦值符合里氏替換原則, 反之 b=a 會(huì)報(bào)錯(cuò)
a = b;

將TS的type看作編程語(yǔ)言

既然ts的type是圖靈完備的,那么它自然可以完成一切計(jì)算,因此可以看作是一門(mén)語(yǔ)言

函數(shù)

在類(lèi)型語(yǔ)境中,可將泛型看做是函數(shù)

type Fn<T> = T; // 看作 const Fn = val => val;

循環(huán)

經(jīng)??梢栽诖a中看到如下寫(xiě)法:

type R = "A" | "B"
type T = {
  [k in R]: k
}

這里[k in R]可看做循環(huán)for(const k in R){}

借助此特性,可以完成如下操作:

type MyPick<T, K extends keyof T> = {
  [k in K]: T[k]
}
type A = MyPick<{a: string, b: number, c: boolean}, "a"|"c">

當(dāng)然這種循環(huán)只針對(duì)特定類(lèi)型("a"|"b"這種),稍微復(fù)雜點(diǎn)的循環(huán)還是得通過(guò)遞歸實(shí)現(xiàn),例子的話(huà),后面用ts type實(shí)現(xiàn)四則運(yùn)算時(shí)會(huì)用到。

條件語(yǔ)句

type支持三元運(yùn)算符,這個(gè)沒(méi)什么好說(shuō)的。。

需要注意的是,type里沒(méi)有等號(hào),但可以用extends代替等號(hào)

type Equal5<T> = T extends 5 ? true : false;

來(lái)點(diǎn)練習(xí)

// eq1: 實(shí)現(xiàn)`GetProp<Obj, K>`(獲取Obj[K]類(lèi)型)
type GetProp<Obj, K> = K extends keyof Obj ? Obj[K] : undefined;
// eq2: 實(shí)現(xiàn)getName<User>
type GetName<User> = GetProp<User, "name">

extends也常和infer一起用于類(lèi)型推斷。

例如

// 實(shí)現(xiàn)KeyOf
type KeyOf<T> = T extends {[k in infer U]: unknown} ? U : never;
// 實(shí)現(xiàn)ValueOf
type ValueOf<T> = T extends { [k in keyof T]: infer U } ? U : never;
// 實(shí)現(xiàn)Parameters和ReturnType
type FuncBase<F, C extends "params"|"return"> = F extends (...params: infer P) => infer R ? (C extends "params" ? P : R) : never;
type Params<F> = FuncBase<F, "params">;
type Return<F> = FuncBase<F, "return">;

賦值

賦值部分參看前面類(lèi)型集合章節(jié),賦值要遵循里氏替換原則。

條件語(yǔ)句章節(jié)提到了infer,或許可以用infer實(shí)現(xiàn)解構(gòu)賦值。

// 需要實(shí)現(xiàn)類(lèi)似js的const {name, ...extra} = user,求extra。(其實(shí)就是Omit方法)
type MyPick<Obj, T extends keyof Obj> = {[k in T]: Obj[k]};
type MyExclude<Obj, T extends keyof Obj> = keyof Obj extends T|(infer U extends keyof Obj) ? U : never;
type MyOmit<Obj, T extends keyof Obj> =  MyPick<Obj, MyExclude<Obj, T>>;
// 實(shí)現(xiàn)數(shù)組的解構(gòu)賦值const [A, ...extra] = arr;
type GetArrBase<T extends unknown[], C extends "first"|"rest"> = T extends [infer First, ...infer Rest] ? (C extends "first"?First: Rest): never;
type GetFirst<T extends unknown[]> = GetArrBase<T, "first">;
type GetRest<T extends unknown[]> = GetArrBase<T, "rest">;

對(duì)象

type的對(duì)象可以類(lèi)比js中的對(duì)象,使用方法如下,注意最后一個(gè)例子

type Obj = {
  name: string;
  age: 20;
}
Obj["name"] // string;
Obj.age // Error
Obj["age"] // 20
Obj['name'|'age'] // string | 20 , 這個(gè)特性很重要?。?!

利用這個(gè)特性,可以完成如下功能

interface Test {
  a: string;
  b: number;
  c: boolean;
}
// 之前不知道這個(gè)特性時(shí),用infer也能達(dá)到同樣的效果,但實(shí)現(xiàn)不如這個(gè)直觀
type ValueOf<T> = T[keyof T];
type R = ValueOf<Test>;

數(shù)組

ts中的數(shù)組分為Array數(shù)組和Tuple元組。

Array數(shù)組是諸如string[]的寫(xiě)法,類(lèi)似java或其他語(yǔ)言的數(shù)組。

Tuple元組更像是js中的數(shù)組,寫(xiě)法是[string, number, boolean]這種。

(注:js中不存在真正意義上的數(shù)組,數(shù)組是在內(nèi)存上開(kāi)辟連續(xù)空間,每個(gè)單元格所占內(nèi)存都一樣,在js中,數(shù)組寫(xiě)成['a', 5555, {a: 1}]都沒(méi)問(wèn)題,顯然在實(shí)現(xiàn)上不是真正的開(kāi)辟了連續(xù)內(nèi)存空間,應(yīng)該是用鏈表模擬的,為了解決鏈表本身查詢(xún)慢的問(wèn)題,應(yīng)該是采用了跳表或者紅黑樹(shù)的方式組織的?)

數(shù)組中需要注意的點(diǎn)如下:

type A = string[];
type B = [string, number, boolean];
// =========================分割線(xiàn)==========================
// 重點(diǎn)注意?。?!
A[0]; // string
A[1]; // string
B[0]; // string
B[1]; // number;
B[0|2]; // string|boolean
// 注意以下寫(xiě)法,為什么可以這么寫(xiě),因?yàn)閚umber是所有數(shù)字的集合
A[number]; // string
B[number]; // string | number | boolean
A["length"]; // number
B["length"]; // 3
// ts數(shù)組同樣可以像js數(shù)組那樣展開(kāi)
type Spread<T extends unknown[]> = [...T]
Spread<[1,2,3]> // [1,2,3]

根據(jù)以上特性,很容易實(shí)現(xiàn)以下練習(xí):

// eq1: 實(shí)現(xiàn) `ItemOf`方法(獲取數(shù)組中項(xiàng)的類(lèi)型)
type ItemOf<T extends unknown[]> = T[number];
// 之前不知道這個(gè)特性時(shí),用infer實(shí)現(xiàn)的代碼如下
type ItemOfByinfer<T> = T extends (infer N)[] ? N : never;
// eq2:實(shí)現(xiàn)`Append`方法
type Append<T extends unknown[], Ele> = [...T, Ele];
// eq3: 實(shí)現(xiàn)返回?cái)?shù)組length+1
// ts雖然無(wú)法實(shí)現(xiàn)加減運(yùn)算,但可以通過(guò)模擬生成對(duì)應(yīng)新類(lèi)型,返回其屬性,從而模擬加減運(yùn)算
type LengthAddOne<T extends unknown[]> = [unknown, ...T]["length"];

四則運(yùn)算

運(yùn)算加減依賴(lài)于元組長(zhǎng)度,因此先定義一些基本方法,注意..由于是依賴(lài)元組長(zhǎng)度,因此無(wú)法算負(fù)數(shù)和小數(shù),只能算正整數(shù)...

(注:雖然無(wú)法計(jì)算負(fù)數(shù)和小數(shù),但ts的type依舊是圖靈完備的,位運(yùn)算也只是01的運(yùn)算,負(fù)數(shù)和小數(shù)都是一堆01的定義,比如把10000看做0,且最后兩位是小數(shù),那么9999就是 -0.01)

// 返回Push后的數(shù)組
type Append<T extends unknown[], E = unknown> = [...T, U];
// 同理,返回Pop后的數(shù)組代碼如下,暫時(shí)用不到
// type RemoveTop<T extends unknown[]> = T extends [...(infer U), unknown] ? U : never;
type Tuple<N extends number, Arr extends unknown[] = []> = Arr["length"] extends N ? Arr : Tuple<N, Append<Arr>>

有了這些基本方法,先實(shí)現(xiàn)加法減法

type Add<A extends number, B extends number> = [...Tuple<A>, ...Tuple<B>]["length"];
type Subtract<A extends number, B extends number> = Tuple<A> extends [...Tuple<B>, ...(infer U)] ? U["length"] : never;

乘法的話(huà),A*B就是A個(gè)B相加,簡(jiǎn)易版乘法如下,思路不難,但直接用Add和Subtract封裝,很多寫(xiě)法都提示嵌套太深。。

注意,這里用于統(tǒng)計(jì)和的參數(shù)S以元組表示,因?yàn)樗羞\(yùn)算都是以元組為基準(zhǔn),S用數(shù)字表示會(huì)先轉(zhuǎn)元組再轉(zhuǎn)數(shù)字,來(lái)來(lái)回回開(kāi)銷(xiāo)比較大。

type MultipleBase<A extends number, B extends number, S extends unknown[] = []> = 
    B extends 0
    ? S["length"]
    : MultipleBase<A, Subtract<B, 1>, [...S, ...Tuple<A>]>;

乘法還有優(yōu)化的空間,例如2*100,直接用這個(gè)算的是100個(gè)2相加,時(shí)間復(fù)雜度不如100*2,而計(jì)算這么優(yōu)化的前提是,實(shí)現(xiàn)BiggerThan方法。

type BiggerThan<A extends number, B extends number> = Tuple<A> extends [...Tuple<B>, ...infer U] ? (U["length"] extends (never|0) ? false : true): false;
// 優(yōu)化后的乘法如下
type Mutiple<A extends number, B extends number> = BiggerThan<A, B> extends true ? MultipleBase<A, B> : MultipleBase<B, A>;

有了BiggerThan除法也好說(shuō),例如a/b,判定b*2、b*3...b*n和A的大小就行。

同乘法的實(shí)現(xiàn),用于統(tǒng)計(jì)的參數(shù)R為元組。。

type Divide<A extends number, B extends number, R extends unknown[] = []> = BiggerThan<B, A> extends true ? R["length"] : Divide<Subtract<A,B>, B, Append<R>>;

至此,四則運(yùn)算實(shí)現(xiàn)完畢。

以上就是typescript type類(lèi)型使用梳理總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于typescript type類(lèi)型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Typescript tsconfig.json的配置詳情

    Typescript tsconfig.json的配置詳情

    這篇文章主要為大家介紹了Typescript tsconfig.json的配置詳情示例 ,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Nest框架中集成使用Swagger示例說(shuō)明

    Nest框架中集成使用Swagger示例說(shuō)明

    這篇文章主要為大家介紹了Nest框架中集成使用Swagger的示例說(shuō)明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • typescript難學(xué)嗎?前端有必要學(xué)?該怎么學(xué)typescript

    typescript難學(xué)嗎?前端有必要學(xué)?該怎么學(xué)typescript

    TypeScript代碼與?JavaScript?代碼有非常高的兼容性,無(wú)門(mén)檻,你把?JS?代碼改為?TS?就可以運(yùn)行。TypeScript?應(yīng)該不會(huì)脫離?JavaScript?成為獨(dú)立的語(yǔ)言。學(xué)習(xí)?TypeScript?應(yīng)該主要指的是學(xué)習(xí)它的類(lèi)型系統(tǒng)。
    2022-12-12
  • TypeScript交叉運(yùn)算的算法示例解析

    TypeScript交叉運(yùn)算的算法示例解析

    這篇文章主要為大家介紹了TypeScript交叉運(yùn)算的算法示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • TypeScript十大排序算法插入排序?qū)崿F(xiàn)示例詳解

    TypeScript十大排序算法插入排序?qū)崿F(xiàn)示例詳解

    這篇文章主要為大家介紹了TypeScript十大排序算法插入排序?qū)崿F(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • d3-scale d3-scaleTime使用示例詳解

    d3-scale d3-scaleTime使用示例詳解

    這篇文章主要為大家介紹了d3-scale d3-scaleTime使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Typescript?extends?關(guān)鍵字繼承類(lèi)型約束及條件類(lèi)型判斷實(shí)現(xiàn)示例解析

    Typescript?extends?關(guān)鍵字繼承類(lèi)型約束及條件類(lèi)型判斷實(shí)現(xiàn)示例解析

    這篇文章主要介紹了Typescript?extends?關(guān)鍵字繼承類(lèi)型約束及條件類(lèi)型判斷實(shí)現(xiàn)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • TypeScript中的聯(lián)合類(lèi)型使用示例詳解

    TypeScript中的聯(lián)合類(lèi)型使用示例詳解

    這篇文章主要為大家介紹了TypeScript中的聯(lián)合類(lèi)型使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • typescript快速上手的基礎(chǔ)知識(shí)篇

    typescript快速上手的基礎(chǔ)知識(shí)篇

    靜態(tài)類(lèi)型的typescript與傳統(tǒng)動(dòng)態(tài)弱類(lèi)型語(yǔ)言javascript不同,在執(zhí)行前會(huì)先編譯成javascript,因?yàn)樗鼜?qiáng)大的type類(lèi)型系統(tǒng)加持,能讓我們?cè)诰帉?xiě)代碼時(shí)增加更多嚴(yán)謹(jǐn)?shù)南拗?。注意,它并不是一門(mén)全新的語(yǔ)言,所以并沒(méi)有增加額外的學(xué)習(xí)成本
    2022-12-12
  • TypeScript十大排序算法之選擇排序?qū)崿F(xiàn)示例詳解

    TypeScript十大排序算法之選擇排序?qū)崿F(xiàn)示例詳解

    這篇文章主要為大家介紹了TypeScript十大排序算法之選擇排序?qū)崿F(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02

最新評(píng)論