需要帮助来转换打字稿助手
Need help to convert typescript helper
我有一个帮手,我正在导出和导入多个文件,它工作正常,但我想稍微改变一下,我正在努力解决这个问题:
// 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
很少会改变,我想让它成为一个可选参数,但如果需要仍然能够通过其他 RequestType。
所以理想情况下,我喜欢上面的解决方案,但用法是:
const actions = createActions(Actions)
具有相同的输出。
如果需要,通过不同的请求类型:
enum TabRequests {
Open,
Close
}
enum TabActions {
Tab
}
const actions = createActions(TabActions, TabRequests);
// actions.Tab.Open -> 'TabOpen'
// actions.Tab.Close -> 'TabClose'
我已经尝试了所有我能想到的方法,但似乎无法弄清楚它的打字稿方面!
你可以使用打字稿 overload signatures, also see the playground:
// 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);
以下是如何在单独的模块中使用 中的重载函数:
// 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
我有一个帮手,我正在导出和导入多个文件,它工作正常,但我想稍微改变一下,我正在努力解决这个问题:
// 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
很少会改变,我想让它成为一个可选参数,但如果需要仍然能够通过其他 RequestType。
所以理想情况下,我喜欢上面的解决方案,但用法是:
const actions = createActions(Actions)
具有相同的输出。
如果需要,通过不同的请求类型:
enum TabRequests {
Open,
Close
}
enum TabActions {
Tab
}
const actions = createActions(TabActions, TabRequests);
// actions.Tab.Open -> 'TabOpen'
// actions.Tab.Close -> 'TabClose'
我已经尝试了所有我能想到的方法,但似乎无法弄清楚它的打字稿方面!
你可以使用打字稿 overload signatures, also see the playground:
// 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);
以下是如何在单独的模块中使用
// 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