具有映射返回类型的通用设置实用程序

问题描述 投票:0回答:1

我正在尝试创建一个提供一些基本返回类型的通用设置实用程序。我们的应用程序将所有设置存储在集中式字典中,我想提供可能类型的映射,而不是手动指定每个键的类型。

举个例子,假设我们有设置键的映射:

const UserSettings = {
  DEFAULT_ORGANIZATION: 'user_profile.default_organization',
  THEME: 'user_profile.theme'
} as const;

我想创建一个相应的地图,如下所示:

type UserSettingsTypes = {
  'user_profile.default_organization': boolean;
  'user_profile.theme': { primary: string; secondary: string };
};

这样我就可以编写一个设置查找函数,如下所示:

const organization = readSetting<UserSettingsTypes>(UserSettings.DEFAULT_ORGANIZATION);

其中

organization
具有正确的
boolean
类型。

我尝试向

readSetting
添加一个泛型,如下所示:

const readSetting = <T extends Record<string, unknown>, K = keyof T>(key: K): T[K] => {
  // ...
};

但它抱怨“类型‘K’不能用于索引类型‘T’”

是否可以提供这样的映射返回类型?

如果是这样,我应该如何构造

K
,以便它可以正确返回
T
中的映射类型?

这是显示问题的示例:https://tsplay.dev/m0d2qm

typescript typescript-generics
1个回答
0
投票

从概念上讲,你想要类似的东西

declare const readSetting:
    <T extends object, K extends keyof T>(key: K) => T[K]

其中

K
约束
keyof T
。不幸的是,你不能调用像
readSetting<UserSettingsTypes>(UserSettings.DEFAULT_ORGANIZATION)
这样的泛型函数,你可以手动 specify
T
但有编译器 infer
K
为你服务。 TypeScript 不支持 microsoft/TypeScript#26242 中要求的部分类型参数推断。您要么必须让编译器推断
T
K
(如果没有
T
类型的参数,这是不可能的),或者您必须手动指定
T
K
(这是多余的)对于
K
)。不,使用像 K = keyof T 这样的
type argument default
没有帮助;你只会得到默认值而不是推理。

除非实现了 microsoft/TypeScript#26242,否则您需要以某种方式解决它。我在这里使用的最常见的解决方法是 currying,您可以将单个通用函数拆分为多个。在你的情况下看起来像:

declare const readSetting:
    <T extends object>() => <K extends keyof T>(key: K) => T[K]

现在您可以调用

readSetting<UserSettingsTypes>()
,手动指定
T
。这将返回一个类型为
<K extends keyof UserSettingsTypes>(key: K) => UserSettingsTypes[K]
的新泛型函数,您可以使用函数参数调用该函数,并且将为您推断出
K

const organization =
    readSetting<UserSettingsTypes>()(UserSettings.DEFAULT_ORGANIZATION);
// const organization: boolean

所以,虽然中间有那个奇怪的函数调用

()
,但它非常接近您最初想要的,并且它为您提供了您期望的返回类型。

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.