簡體   English   中英

TypeScript中的函數定義中的嵌套泛型

[英]Nested Generics in function definition in TypeScript

我正在嘗試為依賴於操作類型的redux操作創建類型安全的處理程序。 例如,任何動作都可以描述為:

type ActionType<T extends string> = {
  type: T
};

對於特定的動作,可以有:

type MyAction = ActionType<'hey' | 'there'>;

現在,我想將處理程序函數限制為僅允許“ hey”或“ there”作為類型。 最后,我期望這樣的事情:

handleAction<MyAction>('hey');

處理程序函數的定義可以是:

function handleAction<A extends ActionType<T>>(type: T){
...
}

但是我有一個打字稿編譯器錯誤:


TS2304:找不到名稱“ T”。


因此,我必須以這種方式修改此處理程序函數定義:

function handleAction<A extends ActionType<T>, T extends string>(type: T){
...
}

它可以工作,但是看起來真的很丑:

handleAction<MyAction, 'hey' | 'there'>('hey');

TS游樂場

有什么更好的方法來解決這個問題?

編輯

您可以使用類型查詢來獲取類型的type

function handleAction<A extends ActionType<string>>(type: A ['type']) {
}

handleAction<MyAction>('hey');

或者,您可以在2.8中使用條件類型從ActionType提取通用參數(在撰寫本文時尚未發布2.8,但將於2018年3月發布,您可以通過npm install -g typescript@next來獲取它)

type ActionType<T extends string> = {
  type: T
};

type MyAction = ActionType<'hey' | 'there'>;


function handleAction<A extends ActionType<string>>(type: A extends ActionType<infer U> ? U : never) {
}

handleAction<MyAction>('hey');

該解決方案基於條件類型推斷行為 ActionType<infer U>基本上說:如果擴展了其他類型U ActionType ,則給我類型U 因此,在本例中, U將是傳遞給ActionType任何字符串文字類型。 然后,我們在條件類型的真實分支上使用U ,這成為out條件類型的最終類型。 在這種情況下,我們不在乎虛假分支,因此我們從不使用。

有兩種方法:

  1. 使用字符串並集。

我喜歡這個,因為它比較簡單(針對您描述的問題):

type FileAction = 'save' | 'read' | 'copy';
function doAction (a) {
}
declare function doAction<A extends string> (action: A): void;

doAction<FileAction>('save'); // good, as desired
doAction<FileAction>('xxx'); // error, as expected
  1. 通過括號符號獲取.type

這看起來更駭人聽聞,但它是一種有效的語法..它不需要您更改對象的形狀。

type FileFile <T extends string> = {
  type: T;
}
type WordFile = FileFile<'why'|'you'|'no'|'work'>;

function doAction2 (a) {
}
declare function doAction2<F extends FileFile<string>> (action: F["type"]): void;

doAction2<WordFile>('no'); // good, as desired 
doAction2<WordFile>('xxx'); // error, as expected

這可以清理一些東西,但是我不確定這是否是您想要的:

type ActionType<T extends string> = {
  type: T
};

type MyWord = 'hey' | 'there';
type MyAction = ActionType<MyWord>;

function handleAction<A extends ActionType<T>, T extends string>(type: T){
}

handleAction<MyAction, MyWord>('hey');

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM