如何用TypeScript模板字面量定义首尾标签匹配的HTML字符串类型
问题根源
你现有实现的问题在于直接将HTML标签名的联合类型传入Template的TAG泛型参数,TypeScript解析模板字面量联合类型时,会对首尾两个TAG位置的联合类型做笛卡尔积组合,导致开头和结尾的标签可以取联合类型中的任意值,自然出现不匹配的情况。
解决方案
可以结合infer和分布式条件类型实现需求,让每个HTML标签单独生成对应的模板类型,再合并为联合类型,保证每个联合项的首尾标签完全一致。
实现代码如下:
type HtmlTag = keyof HTMLElementTagNameMap; // 支持带属性/不带属性的合法HTML模板类型 export type HtmlTemplate<Content extends string> = HtmlTag extends infer Tag ? Tag extends HtmlTag ? `<${Tag}${` ${string}` | ""}>${Content}</${Tag}>` : never : never; // 如果要求必须带属性,可去掉属性位置的 | "" 分支,改为如下写法: export type HtmlTemplateWithAttr<Content extends string> = HtmlTag extends infer Tag ? Tag extends HtmlTag ? `<${Tag} ${string}>${Content}</${Tag}>` : never : never;
效果验证
// 首尾标签匹配的合法值可正常通过校验 const validTemplate: HtmlTemplate<"测试内容"> = `<div class="card">测试内容</div>`; // 首尾标签不匹配的值会触发类型报错 const invalidTemplate: HtmlTemplate<"测试内容"> = `<div>测试内容</span>`; // 类型错误提示:不能将类型"<div>测试内容</span>"分配给类型"HtmlTemplate<"测试内容">"
内容的提问来源于stack exchange,提问作者basti
相关产品推荐
相关产品推荐

