如何基于数组中对象的属性创建类型?

麦克雷奇克

我正在尝试推断配置对象的类型,该配置对象的属性由参数描述数组定义。

简而言之:

// Based on the following array...
const params = [
    { id: "max", example: 75 },
    { id: "label", example: "My Label" },
];

// ...extract values from a request, creating a structure like...
const config = {
    max: 100,
    label: "Max Items",
};

// ... with type:
{ max: number, label: string }

这就是我的代码所取得的成就。

// A simple parameter description interface
type ConfigParameter<IdType, ValueType> = Readonly<{
    // The `IdType` is necessary to get a stricter type
    // parameter instead of a generic `id: string;`. This will be needed
    // later when we infer the type of the `config` object.
    id: IdType;
    example: ValueType;
}>;

// Configuration parameters ------------------------------------

const max: ConfigParameter<"max", number> = {
    id: "max",
    example: 100,
};

const label: ConfigParameter<"label", string> = {
    id: "label",
    example: "My Label",
};

const configParams = [max, label] as const;

// Extracted configuration object ------------------------------
// At some point, the application uses the parameter descriptors
// above to extract data from a request. This is the implementation
// I have so far:

type Config<T extends Readonly<Array<ConfigParameter<string, any>>>> = {
    [key in T[number]["id"]]: T[number]["example"];
};

const config: Config<typeof configParams> = {
    max: 75,
    label: "Some index",
};

现在的问题是,中的所有属性config都具有type number | string,而不是具有各自的类型:

// Expected type
{ max: number, label: string }

// Actual type
{ max: number | string, label: number | string }

我知道为什么会得到这个结果,但是我不知道如何分别限制每个键的类型。

有什么建议?

贾卡尔兹

干得好:

type Config<T extends ReadonlyArray<ConfigParameter<string, any>>> = {
  [K in T[number]["id"]]: Extract<T[number], { id: K }>["example"]
};

此处的区别是使用Extract这是一种实用程序类型,可将相关的部分从联合中取出。应该可以根据需要工作。您可以使用以下命令使其更漂亮(输出,而不是定义):

type Config<T extends ReadonlyArray<ConfigParameter<string, any>>> = {
  [K in T[number]["id"]]: Extract<T[number], { id: K }>["example"]
} extends infer O
  ? { [P in keyof O]: O[P] }
  : never;

现在,您将获得所需的强类型:

const config: Config<typeof configParams> = {
  max: 75,
  label: "Some index"
};
/* const config: {
    max: number;
    label: string;
} */

好吧,希望能有所帮助;祝好运!

链接到代码

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何基于属性合并数组中的对象

如何基于类型化对象数组中的值限制类型?

如何基于TypeScript中的const对象创建对象类型?

如何从 TypeScript 中的对象数组创建类型?

如何从javascript中的对象属性创建数组

从数组类型创建对象类型,其中键是数组中每个对象的属性值

如何基于对象属性创建新对象

如何基于对象数组中的属性进行多级过滤

如何基于对象值创建窄类型

创建作为对象属性数组的类型

如何基于对象的属性创建接口?

如何基于对象数组中的相似值(而非属性)对对象数组执行求和/减运算

如何基于超类型的对象创建子类型的对象?

删除基于属性的数组中的特定对象?

如何基于公共属性将数组中的对象分组为数组数组

创建对象时如何在属性中给出数组的索引

从对象数组中的属性创建对象

从 ReactJS 中的对象属性创建数组数组

如何从Angular中的另一个对象过滤基于属性的对象数组?

如何基于Javascript中的多个数组属性对对象数组进行分组

如何使用基于对象值的键创建对象类型

获取数组中对象的属性类型

如何基于每个对象中的字符串属性数组对数组中的对象进行深层比较/匹配?

如何基于TypeScript中的其他类型使对象属性为可选?

如何基于带有数组的对象创建新对象

如何从基于属性排序的对象列表中创建由对组成的“行”

如何在Angular2对象数组中基于属性值进行过滤?

如何使用react和javascript基于多个条件从对象数组中检索特定属性?

如何基于Javascript中的属性组合两个大小不同的对象数组?