[英]Need help to convert typescript helper
I have a helper I'm exporting and importing into multiple files which is working fine, however I want to change it slightly and I'm struggling to figure this one out:我有一个助手,我正在导出和导入多个工作正常的文件,但是我想稍微改变它,我正在努力解决这个问题:
// 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;
}
Now in another file I'm importing the createActions method & RequestTypes and using it like so:现在在另一个文件中,我正在导入 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'
This all works fine, however RequestTypes
will rarely change, i want to make it an optional argument, but still able to pass through other RequestTypes if needed.这一切都很好,但是RequestTypes
很少会改变,我想让它成为一个可选参数,但如果需要,仍然能够通过其他 RequestTypes。
So idealy by default I'd like the above solution but the usage will be:因此,默认情况下,我希望使用上述解决方案,但用法如下:
const actions = createActions(Actions)
with the same output. const actions = createActions(Actions)
与 output 相同。
And if need be, pass through different RequestTypes:如果需要,通过不同的 RequestTypes:
enum TabRequests {
Open,
Close
}
enum TabActions {
Tab
}
const actions = createActions(TabActions, TabRequests);
// actions.Tab.Open -> 'TabOpen'
// actions.Tab.Close -> 'TabClose'
I've tried everything i can think of but can't seem to figure out the typescript side of this!我已经尝试了我能想到的一切,但似乎无法弄清楚 typescript 的一面!
You can use typescript overload signatures , also see the playground :您可以使用 typescript 重载签名,另请参阅操场:
// 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);
Here's how you can use the overloaded function from the other answer in a separate module:以下是如何在单独的模块中使用来自其他答案的重载 function :
TS Playground link TS Playground 链接
// 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.