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

如何为HTML结构嵌套对象定义TypeScript类型?

为HTML标签嵌套对象定义TypeScript类型

问题背景

你有如下字面量对象:

const objectIdea = {
  form: {
    div: {
      attributes: {
        cssClasses: ["Container", "flex"],
      },
      h1: {
        attributes: {
          text: "Hello world 2!",
        },
      },
    },

    div: {
      h1: {
        text: "And so on."
      },
    },

    main: {
      h1: {
        attributes: {
          text: "Hello world!"
        }
      },
    },
  },
};

该对象的键代表HTML标签,值是包含attributes属性和子HTML标签的对象,目标是通过这个对象自动生成HTML组件,对象支持任意长度和嵌套层级,结构需遵循:

HTMLTag: { 
        attributes: HTMLTagAttributes,  // 应从父标签推断
        HTMLTag:  {      // 子标签
                    attributes: HTMLTagAttributes,     // 应从父标签推断
                    HTMLTag:  // 以此类推
}

你尝试了如下代码但未解决问题:

interface IComponentObject<T extends keyof HTMLElementTagNameMap = keyof HTMLElementTagNameMap> {
  T:{
    attributes: T
    
  }
}

解决方案

要实现这个需求,我们需要用递归类型处理嵌套结构,同时结合TypeScript内置的HTMLElementTagNameMap来关联HTML标签和对应的DOM元素类型,进而推断属性。

步骤1:定义标签对应的属性类型

基于标签对应的DOM元素,提取其可用属性,同时允许自定义额外属性(比如示例中的cssClasses、text):

type AttributesForTag<T extends keyof HTMLElementTagNameMap> = 
  Partial<HTMLElementTagNameMap[T]> & Record<string, any>;

这里用Partial让所有DOM属性变为可选,同时通过Record<string, any>支持自定义属性。

步骤2:定义递归的组件节点类型

组件节点需要包含可选的attributes(对应当前标签的属性),以及任意数量的子标签(递归引用自身类型):

type ComponentNode<T extends keyof HTMLElementTagNameMap = keyof HTMLElementTagNameMap> = {
  attributes?: AttributesForTag<T>;
} & {
  [K in keyof HTMLElementTagNameMap]?: ComponentNode<K>;
};

这个类型的逻辑是:每个节点可以有当前标签的属性,同时可以嵌套任意其他HTML标签作为子节点,子节点同样遵循这个结构。

步骤3:定义根对象类型

根对象是多个顶级HTML标签的集合:

type ComponentObject = {
  [K in keyof HTMLElementTagNameMap]?: ComponentNode<K>;
};

验证类型

现在可以用这个类型约束你的字面量对象:

const objectIdea: ComponentObject = {
  form: {
    div: {
      attributes: {
        cssClasses: ["Container", "flex"],
      },
      h1: {
        attributes: {
          text: "Hello world 2!",
        },
      },
    },

    div: {
      h1: {
        attributes: {
          text: "And so on."
        }
      },
    },

    main: {
      h1: {
        attributes: {
          text: "Hello world!"
        }
      },
    },
  },
};

注意:原示例中第二个div下的h1直接写了text属性,不符合结构要求,需要放到attributes对象中才能通过类型校验。

优化:严格约束自定义属性(可选)

如果希望自定义属性有更严格的类型,比如明确cssClasses是字符串数组、text是字符串,可以修改AttributesForTag:

type CustomAttributes = {
  cssClasses?: string[];
  text?: string;
};

type AttributesForTag<T extends keyof HTMLElementTagNameMap> = 
  Partial<HTMLElementTagNameMap[T]> & CustomAttributes;

这样TypeScript会自动校验自定义属性的类型,避免错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 21:50:38