ts?類型體操?Chainable?Options?可鏈?zhǔn)竭x項(xiàng)示例詳解
問題
在JavaScript我們通常會(huì)使用到可串聯(lián)(Chainable/Pipline)的函數(shù)構(gòu)造一個(gè)對(duì)象,但是在Typescript中,你能合理地給它賦上類型嗎?
題目是: 可以使用任何你喜歡的方式實(shí)現(xiàn)這個(gè)類型 - interface, type, 或者 class 都行。你需要提供兩個(gè)函數(shù)option(key, value)
和 get()
在 option
中你需要使用提供的key和value來擴(kuò)展當(dāng)前的對(duì)象類型,通過 get()
獲取最終結(jié)果。
注意: 你只需要在類型層面實(shí)現(xiàn)這個(gè)功能 - 不需要實(shí)現(xiàn)任何 ts/js 的實(shí)際邏輯。 你可以假設(shè)key
只接受字符串而value
接受任何類型,你只需要暴露它傳遞的類型而不需要進(jìn)行任何處理。同樣的key
只會(huì)被使用一次。
例子是:
declare const config: Chainable const result = config .option('foo', 123) .option('bar', { value: 'Hello World' }) .option('name', 'type-challenges') .get() // expect the type of the result to be: interface Result { foo: number name: string bar: { value: string } }
答案
type Chainable = { option(key: string, value: any): any get(): any }
把這個(gè)any改成答案即可。作者要求我們做什么?需要實(shí)現(xiàn)兩個(gè)方法,一個(gè)是options(key, value)
,另一個(gè)是get()
。
option(key, value): 必須在某處累加 key
和 value
的類型信息。累加操作必須持續(xù)進(jìn)行,直到調(diào)用get
函數(shù)將累加的信息作為一個(gè)對(duì)象類型返回。
先看看提供的樣例:
const result1 = a .option('foo', 123) .option('bar', {value: 'Hello World'}) .option('name', 'type-challenges') .get() 希望得到的是: type Expectd1 = { foo: number, bar: { value: string }, name: string }
傳參
把option傳的key
值和value
值給對(duì)應(yīng)改了。所以我們把key
和value
的any
替換成類型參數(shù),以便ts可以推斷出它們的類型并將其分配給類型參數(shù):
type Chainable<T = {}> = { option<K, V>(key: K, value: V): any get(): any }
我們現(xiàn)在有了關(guān)于key
和value
的類型信息。ts會(huì)將key
推斷為字符串字面量類型, 而將value
推斷為常見的類型。
例如: 調(diào)用option('foo', 123)
將得出的類型為: key = 'foo‘ 和 value = number
我們有了信息后,把它存儲(chǔ)在哪里呢?它必須是一個(gè)在若干次方法調(diào)用中保持其狀態(tài)的地方。唯一的地方便是Chainable
類型本身。
讓我們?yōu)?code>Chainable類型添加一個(gè)新的類型參數(shù)T
,并且不能忘記默認(rèn)它是一個(gè)空對(duì)象。
type Chainable<T = {}> = {}
option部分
注意,我們希望option(key, value)
返回Chainable
類型本身(我們希望有可能進(jìn)行鏈?zhǔn)秸{(diào)用),但是要將類型信息累加到其類型參數(shù)中。
那么我們使用&
來將新的類型添加到累加器中:
type Chainable<T = {}> = { option<K, V>(key: K, value: V): Chainable<T & { [k in K] : V }>; get(): any }
這里值得提一下為什么是 { [k in K] : V }, 直接寫 { K : V } 不行嗎?為什么還要in一下?
由于K是類型,類型是不能直接當(dāng)成key的,在ts中對(duì)象如若想要以類型來當(dāng)key也就是類型當(dāng)鍵,要[k in K]
這樣寫才行。
比如說: 定義一個(gè)類型key value這種字面量的對(duì)象,當(dāng)時(shí)必須value是string類型。
type a<K extends string> = {[k in K]: string}
type b = a<> const c:b = { a: 'c' }
那接上面,所以這個(gè)K必須是string類型,js中字面量的key必須是string類型。所以改一下:
type Chainable<T = {}> = { option<K extends string, V>(key: K, value: V): Chainable<T & { [k in K] : V }>; get(): any }
get
那么,這個(gè)get()函數(shù)調(diào)用的時(shí)候,應(yīng)該返回什么呢,它必須從Chainable
返回類型參數(shù)T
,也就是option(key, value)
鏈?zhǔn)秸{(diào)用所得到的的這么一個(gè)對(duì)象,也就是option(key, value)一直點(diǎn)調(diào)用的整體類型信息,那么就是傳入的這個(gè)參數(shù)也就是T本身。
type Chainable<T = {}> = { option<K extends string, V>(key: K, value: V): Chainable<T & { [k in K] : V }>; get(): T }
那么這樣就完成了嗎?我們來看一下測(cè)試結(jié)果
怎么還有紅色波浪線,我們來看看
const result2 = a .option('name', 'another name') // @ts-expect-error .option('name', 'last name') .get()
哦,原來是這個(gè)對(duì)象中key相同的了,就不用再點(diǎn)調(diào)用下去了,直接省略。那么也就是說這個(gè)key的類型要控制一下,當(dāng)判斷到這個(gè)key已經(jīng)存在了,我們就略過
type Chainable<T = {}> = { option<K extends string, V>(key: K extends keyof T ? never : K, value: V): Chainable<T & { [k in K] : V }>; get(): T }
單拎出來看看
key: K extends keyof T ? never : K
至此,完成這一道題!
以上就是ts 類型體操 Chainable Options 可鏈?zhǔn)竭x項(xiàng)示例詳解的詳細(xì)內(nèi)容,更多關(guān)于ts 類型Chainable Options的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
TypeScript類型編程中的extends和infer示例解析
這篇文章主要為大家介紹了TypeScript類型編程中的extends和infer示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08Typescript編碼規(guī)范ESLint和Prettier使用示例詳解
這篇文章主要介紹了Typescript編碼規(guī)范ESLint和Prettier使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09TypeScript快速學(xué)習(xí)入門基礎(chǔ)語(yǔ)法
TypeScript的基礎(chǔ)語(yǔ)法,包括變量聲明、復(fù)合類型(數(shù)組和對(duì)象)、條件控制(if-else和switch)、循環(huán)(for和while)、函數(shù)(基礎(chǔ)和箭頭函數(shù),以及可選參數(shù))、面向?qū)ο筇匦裕杜e、接口、繼承)以及模塊開發(fā)中的導(dǎo)出和導(dǎo)入2024-07-07TypeScript之Generics泛型類型學(xué)習(xí)
這篇文章主要為大家介紹了TypeScript之Generics泛型類型學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07高級(jí)前端面試手寫扁平數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)Tree
這篇文章主要為大家介紹了高級(jí)前端面試手寫扁平數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)Tree示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06TypeScript逆變之條件推斷和泛型的應(yīng)用示例詳解
這篇文章主要為大家介紹了TypeScript逆變之條件推斷和泛型的應(yīng)用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09TypeScript十大排序算法之選擇排序?qū)崿F(xiàn)示例詳解
這篇文章主要為大家介紹了TypeScript十大排序算法之選擇排序?qū)崿F(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02簡(jiǎn)單三行代碼函數(shù)實(shí)現(xiàn)幾十行Typescript類型推導(dǎo)
這篇文章主要為大家介紹了簡(jiǎn)單三行代碼函數(shù)實(shí)現(xiàn)幾十行Typescript類型推導(dǎo)的方案示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01TypeScript開發(fā)HapiJS應(yīng)用詳解
這篇文章主要為大家介紹了TypeScript開發(fā)HapiJS應(yīng)用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08