gpt4 book ai didi

javascript - 在 TypeScript 中包装函数的嵌套对象?

转载 作者:搜寻专家 更新时间:2023-10-30 21:36:39 25 4
gpt4 key购买 nike

我正在使用 Redux 并将商店数据分解为“切片”。每个“切片”对应一个区域,例如 userscomments。我将每个切片的选择器组合到一个顶级 selectors 模块中,我可以在整个应用程序中访问该模块。

切片的格式是:

export interface IUsersSelectors {
getCurrentUser(state: IUsersState): IUser | undefined;
}

const selectors: IUsersSelectors = {
getCurrentUser(state: IUsersState) {
return state.currentUser;
}
};

export default {
getInitialState,
reducer,
selectors
};

然后全部导入,并组合选择器:

export const selectors = Object.keys(slices).reduce((combinedSelectors: any, sliceKey: string) => {
const sliceSelectors = slices[sliceKey].selectors;

combinedSelectors[sliceKey] = Object.keys(sliceSelectors).reduce((selectorsMap: object, selectorKey: string) => {
const localizedSelector = sliceSelectors[selectorKey];

selectorsMap[selectorKey] = (globalState, ...args: any[]): any => {
return localizedSelector(globalState[sliceKey], ...args);
};

return selectorsMap;
}, {});

return combinedSelectors;
}, {});

然后在整个应用程序中使用:

selectors.users.getCurrentUser(store.getState());

这意味着选择器在检索数据时期望只是它们的切片状态,但它们实际上是用全局存储状态调用的。我基本上只是将它们包装在另一个管理作用域的函数中。

我最接近于为此定义通用类型的是:

type IScopedSelector<T extends () => any> = (globalState: IStoreState, ...args: any[]) => ReturnType<T>;

type IScopedSelectors<T> = {
[K in keyof T]: IScopedSelector<T[K]>;
};

type INestedScopedSelectors<R> = {
[S in keyof R]: IScopedSelectors<R[S]>;
};

export const selectors: INestedScopedSelectors<ISelectors>...

其中 ISelectors 是形状的简单接口(interface):

export interface ISelectors {
users: IUsersSelectors;
}

但是,当我尝试将 T[K] 传递给 IScopedSelector 时,我在输入时遇到错误,因为它必须是一个函数:

[ts] Type 'T[K]' does not satisfy the constraint '() => any'.

如果我删除 extends () => any,则会收到有关 ReturnType 的错误:

[ts] Type 'T' does not satisfy the constraint '(...args: any[]) => any'.

理想情况下,我也会保持选择器参数的类型(而不是 ...args: any[]),只是将第一个参数覆盖为全局存储状态。

有没有更好的方法来处理这样的嵌套泛型?这可能吗?

最佳答案

您需要为 IScopedSelectors 的通用类型添加相似的类型约束。和 INestedScopedSelectors .

如果没有这样的约束,您已经告诉 TypeScript TIScopedSelectors<T>可以是任何类型。所以IScopedSelectors<string>应该是有效的。但是 TypeScript 正确地指出,对于许多类型(例如 string ), [K in keyof T]: IScopedSelector<T[K]>不会工作,因为不能保证 T[K]遵守 IScopedSelector 施加的约束.

所以解决方案只是为两个接口(interface)添加一个约束,以便 TypeScript 具有这种保证。为此,内置 Record类型可能会有帮助。所以像这样:

type IScopedSelectors<T extends Record<string, () => any>> = {
[K in keyof T]: IScopedSelector<T[K]>; // T[K] is now guaranteed to adhere to () => any
};

type INestedScopedSelectors<R extends Record<string, Record<string, () => any>>> = {
[S in keyof R]: IScopedSelectors<R[S]>; // Similarly, R[S] is now guaranteed to adhere to Record<string, () => any>, exactly what IScopedSelectors is expecting.
};

您可能想要替换 Record根据您的具体用例使用更具体的类型,但解决方案本质上是相同的。只需确保将您的约束一直转发到层次结构中。

希望对您有所帮助!

关于javascript - 在 TypeScript 中包装函数的嵌套对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50402388/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com