You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中从给定对象数组动态推断/映射类型?

TypeScript从对象数组动态生成指定结构的映射类型

给定如下对象数组:

const options = [
  { name: "diameter", type: "number", value: 10, min: 0, max: 10 },
  { name: "height", type: "number", value: 2, min: 0, max: 8 },
  { name: "thickness", type: "number", value: 2, min: 0, max: 8 },
  { name: "text", type: "string", value: "Hello World" },
];

需要生成如下结构的类型:

type OptionsType = {
  diameter: { value: number; min: number; max: number };
  height: { value: number; min: number; max: number };
  thickness: { value: number; min: number; max: number };
  text: { value: string };
};

原方案的问题

之前尝试的方案仅能生成number类型的结构,核心原因有两点:

  1. 原数组未添加类型断言,TypeScript自动将数组类型拓宽为包含所有属性的联合数组,丢失了每个元素的精确字面量类型信息(比如name的具体字符串值、type的字面量类型)。
  2. 映射类型中的Extract<T[number], { name: K }>逻辑错误,K是数组元素的类型而非name的类型,导致无法正确筛选对应元素的类型。

解决方案

步骤1:为数组添加as const断言

通过as const让TypeScript保留数组每个元素的精确字面量类型,避免类型自动拓宽:

const options = [
  { name: "diameter", type: "number", value: 10, min: 0, max: 10 },
  { name: "height", type: "number", value: 2, min: 0, max: 8 },
  { name: "thickness", type: "number", value: 2, min: 0, max: 8 },
  { name: "text", type: "string", value: "Hello World" },
] as const;

步骤2:修正类型转换工具ParamType

直接基于元素的完整类型进行条件判断,确保能正确匹配type的字面量值:

type ParamType<T> = 
  T extends { type: "number" } 
    ? { value: number; min: number; max: number }
    : T extends { type: "string" }
      ? { value: string }
      : never;

如果需要保留原数组中value的精确字面量类型(比如10而非number),可以优化为:

type ParamType<T> = 
  T extends { type: "number"; value: infer V; min: infer Min; max: infer Max }
    ? { value: V; min: Min; max: Max }
    : T extends { type: "string"; value: infer V }
      ? { value: V }
      : never;

步骤3:修正映射类型OptionsParams

遍历元组的每个元素类型,将元素的name作为键,对应值为ParamType处理后的类型:

type OptionsParams<T extends readonly { name: string }[]> = {
  [K in T[number] as K["name"]]: ParamType<K>;
};

步骤4:生成目标类型

type OptionsType = OptionsParams<typeof options>;

最终生成的OptionsType完全符合预期结构:

type OptionsType = {
    diameter: {
        value: number;
        min: number;
        max: number;
    };
    height: {
        value: number;
        min: number;
        max: number;
    };
    thickness: {
        value: number;
        min: number;
        max: number;
    };
    text: {
        value: string;
    };
};

内容的提问来源于stack exchange,提问作者Taner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 16:57:38