這個問題的規範答案取決於你的確切用例。我假設你需要Action
來準確評估你寫的類型;也就是type: "DO_X"
的對象不是有任何形式的財產。這意味着createAction("DO_X")
應該是零參數的函數,而createAction("DO_Y")
應該是單個string
參數的函數。我還將假設您想要自動推斷createAction()
上的任何類型參數,因此您不需要爲Blah
的任何值指定createAction<Blah>("DO_Z")
。如果解除這些限制中的任何一個,則可以將解決方案簡化爲類似於@Arnavion提供的解決方案。
打字稿不喜歡物業值映射類型,但它高興地物業這麼做鍵。因此,讓我們以一種爲編譯器可用來幫助我們的類型提供類型的方式構建Action
類型。首先,我們描述了有效載荷的每一個動作類型是這樣的:
type ActionPayloads = {
DO_Y: string;
DO_Z: number;
}
我們還引入任何Action
類型,而有效載荷:
type PayloadlessActionTypes = "DO_X" | "DO_W";
(我已經添加了'DO_W'
型只是爲了顯示它是如何工作,但你可以刪除它)。
現在,我們終於能夠表達Action
:
type ActionMap = {[K in keyof ActionPayloads]: { type: K; payload: ActionPayloads[K] }} & {[K in PayloadlessActionTypes]: { type: K }};
type Action = ActionMap[keyof ActionMap];
的ActionMap
類型是一個對象,它的鍵是每個Action
的type
,並且其值是Action
工會的相應元素。它是Action
s與s的交點,以及Action
而不是s的交點。而Action
只是ActionMap
的值類型。確認Action
是您所期望的。
我們可以用ActionMap
幫我們輸入createAction()
函數。那就是:
function createAction<T extends PayloadlessActionTypes>(type: T):() => ActionMap[T];
function createAction<T extends keyof ActionPayloads>(type: T): (payload: ActionPayloads[T]) => ActionMap[T];
function createAction(type: string) {
return (payload?: any) => (typeof payload === 'undefined' ? { type } : { type, payload });
}
這是一個重載函數與對應的Action
的type
要創建一個類型參數T
。前兩個聲明描述了兩種情況:如果T
是type
的Action
而沒有,則返回類型是返回正確類型Action
的零參數函數。否則,它是一個單參數函數,它採用正確類型的並返回正確類型Action
。實施(第三簽名和身體)與你相似,不同之處在於,如果在沒有通過它不添加的結果。
全部完成!我們可以看到,它的工作原理是期望:
var x = createAction("DO_X")(); // x: { type: "DO_X"; }
var y = createAction("DO_Y")("foo"); // y: { type: "DO_Y"; payload: string; }
var z = createAction("DO_Z")(5); // z: { type: "DO_Z"; payload: number; }
createAction("DO_X")('foo'); // too many arguments
createAction("DO_X")(undefined); // still too many arguments
createAction("DO_Y")(5); // 5 is not a string
createAction("DO_Z")(); // too few arguments
createAction("DO_Z")(5, 5); // too many arguments
你可以看到這一切在行動on the TypeScript Playground。希望對你有效。祝你好運!
您是否嘗試過類似於(type:Type)的定義:(payload:Payload)=> {type:Type,payload:Payload}? –
@EmrysMyrooin這似乎並不奏效。類型被用作值。但仿製藥似乎是朝着正確方向邁出的一步。 TypeScript如何知道'Type'和'Payload'來自'Action'? – daGrevis
何你在Typescript ...我沒有檢查過標籤。我實際上不知道,我正在使用Flow進行打字! –