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

例如,假设我们有设置键的 map :

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

我想创建一个相应的 map ,看起来像:

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

这样我就可以编写一个设置查找函数,看起来像:

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

其中organization具有boolean的正确类型.

我try 在readSetting中添加一个通用名称,看起来像:

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

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

Is it possible to provide a mapped return type like this?

If so, how should I structure 100 so that it can correctly return the mapped type in 101?

以下是显示该问题的示例:https://tsplay.dev/m0d2qm

推荐答案

从概念上讲,您想要这样的东西

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

其中Kconstrainedkeyof T. 不幸的是,您无法调用像readSetting<UserSettingsTypes>(UserSettings.DEFAULT_ORGANIZATION)这样的通用函数,手动调用specify T,但有编译器infer K. TypScript不支持microsoft/TypeScript#26242中请求的partial type argument inference.您要么必须让编译器推断bothTK(如果没有T类型的参数,这是不可能的),要么您必须手动指定TK(这对于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 link to code

Typescript相关问答推荐

排序更改数组类型

如何根据另一个属性的布尔值来缩小函数属性的返回类型?

打印脚本丢失函数的泛型上下文

TypeScrip原始字符串没有方法

为什么我的条件类型不能像我预期的那样工作?

类型TTextKey不能用于索引类型 ;TOption

具有自引用属性的接口

将具有Readonly数组属性的对象接口转换为数组

确保对象列表在编译时在类型脚本中具有唯一键

我在Angular 17中的environment.ts文件中得到了一个属性端点错误

在Cypress中,是否可以在不标识错误的情况下对元素调用.Click()方法?

为什么&Quot;元素隐式具有';Any';类型,因为...即使我已经打字了,也不能作为索引显示错误吗?

对有效枚举值的常量字符串进行常规判断

将接口映射到交叉口类型

声明遵循映射类型的接口

react 路由不响应参数

如何正确地将元组表格输入到对象数组实用函数(如ZIP)中,避免在TypeScrip 5.2.2中合并所有值

Typescript .根据枚举输入参数返回不同的对象类型

React-Router V6 中的递归好友路由

当受其他参数限制时,通用参数类型不会缩小