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

TypeScript:嵌套对象属性的联合类型收窄问题

TypeScript 类型收窄问题:通过type属性识别具体类型

我编写了以下TypeScript代码,目标是让TypeScript通过对象的type属性,自动识别values中name属性为DesignValueText类型,但目前访问values.name.text时会报错,提示“类型‘DesignValue’上不存在属性‘text’”和“类型‘DesignValueHtml’上不存在属性‘text’”。

type DesignValueType = "text" | "html" | "image";
type BaseDesignValue<TType extends DesignValueType, TProps> = TProps & {
  type: TType;
};
type DesignValueText = BaseDesignValue<"text", { text: string }>;
type DesignValueHtml = BaseDesignValue<"html", { html: string }>;
type DesignValueImage = BaseDesignValue<"image", { url: string }>;
type DesignValue = DesignValueText | DesignValueHtml | DesignValueImage;
type DesignValues<TInitialValues> = Record<keyof TInitialValues, DesignValue>;

const initialValues = {
  name: { type: "text" as const, text: "" },
  handler: { type: "text" as const, text: "" },
  text: { type: "html" as const, html: "" },
  profile: { type: "image" as const, url: "" },
};

const displayName = (values: DesignValues<typeof initialValues>) => {
  // 类型“DesignValue”上不存在属性“text”。
  // 类型“DesignValueHtml”上不存在属性“text”。
  return values.name.text;
};

解决方案

问题出在DesignValues类型的定义上,原Record类型会将所有属性统一设为DesignValue联合类型,丢失了每个键对应的具体子类型信息。我们需要改用映射类型,根据初始值中每个属性的type来映射到对应的具体DesignValue子类型:

type DesignValues<TInitialValues extends Record<string, DesignValue>> = {
  [K in keyof TInitialValues]: 
    TInitialValues[K]['type'] extends 'text' ? DesignValueText :
    TInitialValues[K]['type'] extends 'html' ? DesignValueHtml :
    TInitialValues[K]['type'] extends 'image' ? DesignValueImage :
    never;
};

原理说明

  • 映射类型[K in keyof TInitialValues]遍历TInitialValues的每个键
  • 通过条件类型判断每个键对应的type属性值,匹配到对应的DesignValueText/DesignValueHtml/DesignValueImage类型
  • 这样TypeScript就能准确推断values.name的类型为DesignValueText,访问values.name.text时不会再报错

修改后的代码中,displayName函数可以正常访问values.name.text,TypeScript会正确识别其类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 21:17:10