我有一個助手,我正在匯出和匯入多個檔案,它作業正常,但是我想稍微改變它,我正在努力解決這個問題:
// utils.ts
export enum RequestTypes {
Request,
Success,
Failure,
}
type CombineEnums<P, C> = {
[KP in keyof P]: {
[KC in keyof C]: KP extends string ? KC extends string ? `${KP}${KC}` : never : never;
};
};
export function createActions <P, C>(actionTypes: P, requestTypes: C): CombineEnums<P, C> {
const result: any = {};
for (const keyP of Object.keys(actionTypes)) {
result[keyP] = {};
for (const keyC of Object.keys(requestTypes)) {
result[keyP][keyC] = `${keyP}${keyC}`;
}
}
return result;
}
現在在另一個檔案中,我正在匯入 createActions 方法和 RequestTypes 并像這樣使用它:
// module.ts
import { createActions, RequestTypes } from './utils.ts';
enum Actions {
Find,
Create
}
const actions = createActions(Actions, RequestTypes);
// actions.Find.Request -> 'FindRequest'
// actions.Find.Success -> 'FindSuccess'
// actions.Create.Failure -> 'CreateFailure'
這一切都很好,但是RequestTypes很少會改變,我想讓它成為一個可選引數,但如果需要,仍然能夠通過其他 RequestTypes。
所以理想情況下,我想要上述解決方案,但用法是:
const actions = createActions(Actions) 具有相同的輸出。
如果需要,通過不同的請求型別:
enum TabRequests {
Open,
Close
}
enum TabActions {
Tab
}
const actions = createActions(TabActions, TabRequests);
// actions.Tab.Open -> 'TabOpen'
// actions.Tab.Close -> 'TabClose'
我已經嘗試了我能想到的一切,但似乎無法弄清楚打字稿的一面!
uj5u.com熱心網友回復:
您可以使用打字稿多載簽名,另請參閱操場:
// signature for only one argument
export function createActions <P>(actionTypes: P): CombineEnums<P, typeof RequestTypes>;
// signature for two arguments
export function createActions <P, C>(actionTypes: P, requestTypes: C): CombineEnums<P, C>;
// actual implementation with default value for second argument
export function createActions <P>(actionTypes: P, requestTypes: any = RequestTypes): CombineEnums<P, any> {
const result: any = {};
for (const keyP of Object.keys(actionTypes)) {
result[keyP] = {};
for (const keyC of Object.keys(requestTypes)) {
result[keyP][keyC] = `${keyP}${keyC}`;
}
}
return result;
}
// If you want you could also use the following line as implementation signature
// export function createActions <P, C>(actionTypes: P, requestTypes: C | typeof RequestTypes = RequestTypes): CombineEnums<P, C | typeof RequestTypes> {
// Now you can use both signatures, typesafe.
const actionsWithRequestTypeArgument = createActions(Actions, RequestTypes);
const actionsWithoutRequestTypeArgument = createActions(Actions);
uj5u.com熱心網友回復:
以下是如何在單獨的模塊中使用其他答案中的多載函式:
TS 游樂場鏈接
// utils.ts
type StringEnum = Record<string, string>;
export type NestedCombinedStringEnum<
P extends StringEnum,
C extends StringEnum,
> = {
[KP in keyof P]: {
[KC in keyof C]: KP extends string ? KC extends string ? `${KP}${KC}` : never : never;
};
};
export function nestAndCombineStringEnums <
P extends StringEnum,
C extends StringEnum,
>(enumParent: P, enumChild: C): NestedCombinedStringEnum<P, C> {
const result: any = {};
for (const keyP of Object.keys(enumParent)) {
result[keyP] = {};
for (const keyC of Object.keys(enumChild)) {
result[keyP][keyC] = `${keyP}${keyC}`;
}
}
return result;
}
export enum RequestType {
Request = 'Request',
Success = 'Success',
Failure = 'Failure',
}
export function createActions <
P extends StringEnum,
C extends StringEnum,
>(enumParent: P, enumChild: C): NestedCombinedStringEnum<P, C>;
export function createActions <P extends StringEnum>(enumParent: P): NestedCombinedStringEnum<P, typeof RequestType>;
export function createActions <
P extends StringEnum,
C extends StringEnum,
>(enumParent: P, enumChild?: C) {
return nestAndCombineStringEnums(enumParent, enumChild ?? RequestType);
}
// module.ts
import {createActions, RequestType} from './utils.ts';
enum ActionType {
Find = 'Find',
Update = 'Update',
Create = 'Create',
}
const actions = createActions(ActionType); // same as createActions(ActionType, RequestType);
console.log(actions.Create.Success); // "CreateSuccess"
console.log(actions); // the expected result object in your question
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/375628.html
標籤:javascript 打字稿 枚举 柯里化
上一篇:如何動態渲染圖示?
下一篇:如何跳過導致例外的鏈式承諾?
