Typescript 4_ 那些奇怪的字(上) extends, infer, typeof

這篇中途有點難產,畢竟我好像不小心難度拉太高了,所以在思考名詞解釋的情況的時候都是有點不太合適的感覺...另外這些關鍵字詞有 extends, infer, typeof, as, in, keyof, never, unknown, void, static, get, set, readonly,前面會先介紹一部分。

在這篇中,來介紹一下會在typescript看到的關鍵字詞

extends 繼承屬性

extends 的使用上,跟前一篇&的使用有那麼一點的類似,不過在typescript的用法更偏向於物件導向的繼承/inheritance的概念。

那...什麼是繼承?就請去找oop相關的書籍,這邊就不再贅述了。畢竟寫oop的前輩對於繼承的相關說明都很透徹了,就無需我再重新解釋:P

有趣的是在typescript的實作中,extends是可以拿來做conditional type來實作的。

也就是可以利用3元表達式 a ? b : c 來對 generic type 做更進一步的屬性判定。

interface IFoo {
    props: string;
}

interface IFooReturn {
    result: string;
}

interface IBar {
    name: string;
}

interface IBarReturn {
    result: number;
}

function Sample<T>(arg: T): T extends IFoo ? IFooReturn : IBarReturn;

而 conditional type 搭配 infer 就有各種的實作產生

infer type inference 取得function裡面的數值

就如字面上的意義來說,這個是常用來取得 function 裡面的參數值,在 typescript 內建函數 utility types 中,可以看到其實作 ReturnType 的內容。

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

有關utility types的各項函數說明,之後會再提到

另外也可以使用 infer 直接提取 Promise 的回傳值

type PromiseResolve<T> = T extends Promise<infer P> ? P : never;

let foo: PromiseResolve<Promise<string>> // 等同 let foo: string

typeof 懶人的救星

在寫js常常需要使用到 typeof 檢查型別是否是我們想要的格式,在 typescript 的 definition 裡面,也可以利用typeof的好用屬性,讓我們快速建立型別...如果不想寫interface的話

const payload = {
    gate: true,
    id: 0,
    name: 'test'
};

// 使用 alias type
type TPayload = typeof payload;

這樣就會自動建立payload的對應型別出來了

不僅僅是object,function也是可以直接指定出來

function Foo () {
    return 'bar';
}

type TFnFoo = typeof Foo; // () => string

然後可以跟上面的 ReturnType 和 PromiseResolve 做一次組合

async function service () {
    const result = await fetch(/* url */).then(res => res.json())
    
    const map = result.map(/* do something with result */)
    
    return map;
}

type TFoo = PromiseResolve<ReturnType<typeof service>>;

這樣我就可以先行宣告 TFoo 即 service() 回傳且經過處理的內容,而且去掉Promise的部分。

雖然很方便,不過...還是建議勤勞點定義好interface XD

目前來說,最難的部分已經過去了,extends的conditional type的用法,infer取出 function 中的參數,typeof 取得已經設定好value的型別。

下一篇 大概就是 as / in / keyof 上場了...吧?

留言

這個網誌中的熱門文章

ts-node 應用

ubuntu 日常(X)紀錄

Angular 2 with Third Party files