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

如何用TypeScript模板字面量类型实现可组合的CardSize类型?

实现方案

版本一:无额外约束的最简实现

如果你不需要强制校验「同断点唯一值」「无重复值」的规则,只需要保证所有片段都是合法值、无string兜底,直接用递归模板字面量即可:

type Size = 'compact' | 'normal';
type Breakpoint = 'small' | 'medium' | 'large';
// 单个合法值
type SingleCardSize = Size | `${Size}@${Breakpoint}`;
// 递归支持任意空格分隔的组合
type CardSize = SingleCardSize | `${SingleCardSize} ${CardSize}`;

校验效果

// 合法
const s1: CardSize = 'compact';
const s2: CardSize = 'compact@small normal@large';
const s3: CardSize = 'compact compact@small normal@medium';

// 非法(会抛出类型错误)
const e1: CardSize = 'big'; // 非法值
const e2: CardSize = 'compact@xsmall'; // 非法断点

版本二:满足双约束的精准实现

如果需要严格满足「同一断点仅可出现一个值」「值顺序不影响校验」的规则,由于你的场景可选维度非常少(仅1个静态值位 + 3个断点值位),可以直接枚举所有合法排列组合,类型100%精准,无性能问题:

type Size = 'compact' | 'normal';
type Breakpoint = 'small' | 'medium' | 'large';

// 定义各独立位的可选片段,每个位最多出现1次
type StaticPart = Size;
type SmallPart = `${Size}@small`;
type MediumPart = `${Size}@medium`;
type LargePart = `${Size}@large`;

// 多片段全排列工具类型
type TwoPart<A extends string, B extends string> = `${A} ${B}` | `${B} ${A}`;
type ThreePart<A extends string, B extends string, C extends string> = 
  | `${A} ${B} ${C}` | `${A} ${C} ${B}`
  | `${B} ${A} ${C}` | `${B} ${C} ${A}`
  | `${C} ${A} ${B}` | `${C} ${B} ${A}`;
type FourPart<A extends string, B extends string, C extends string, D extends string> =
  | `${A} ${B} ${C} ${D}` | `${A} ${B} ${D} ${C}` | `${A} ${C} ${B} ${D}` | `${A} ${C} ${D} ${B}` | `${A} ${D} ${B} ${C}` | `${A} ${D} ${C} ${B}`
  | `${B} ${A} ${C} ${D}` | `${B} ${A} ${D} ${C}` | `${B} ${C} ${A} ${D}` | `${B} ${C} ${D} ${A}` | `${B} ${D} ${A} ${C}` | `${B} ${D} ${C} ${A}`
  | `${C} ${A} ${B} ${D}` | `${C} ${A} ${D} ${B}` | `${C} ${B} ${A} ${D}` | `${C} ${B} ${D} ${A}` | `${C} ${D} ${A} ${B}` | `${C} ${D} ${B} ${A}`
  | `${D} ${A} ${B} ${C}` | `${D} ${A} ${C} ${B}` | `${D} ${B} ${A} ${C}` | `${D} ${B} ${C} ${A}` | `${D} ${C} ${A} ${B}` | `${D} ${C} ${B} ${A}`;

// 聚合所有合法组合
type SingleCardSize = StaticPart | SmallPart | MediumPart | LargePart;
type TwoCardSize = 
  | TwoPart<StaticPart, SmallPart> | TwoPart<StaticPart, MediumPart> | TwoPart<StaticPart, LargePart>
  | TwoPart<SmallPart, MediumPart> | TwoPart<SmallPart, LargePart> | TwoPart<MediumPart, LargePart>;
type ThreeCardSize =
  | ThreePart<StaticPart, SmallPart, MediumPart> | ThreePart<StaticPart, SmallPart, LargePart>
  | ThreePart<StaticPart, MediumPart, LargePart> | ThreePart<SmallPart, MediumPart, LargePart>;
type FourCardSize = FourPart<StaticPart, SmallPart, MediumPart, LargePart>;

// 最终类型
type CardSize = SingleCardSize | TwoCardSize | ThreeCardSize | FourCardSize;

校验效果

// 合法
const s1: CardSize = 'compact';
const s2: CardSize = 'compact@small normal@large';
const s3: CardSize = 'normal@large compact@small'; // 顺序不同不报错
const s4: CardSize = 'compact compact@small normal@medium';

// 非法(会抛出类型错误)
const e1: CardSize = 'compact@small normal@small'; // 同断点多个值
const e2: CardSize = 'compact compact'; // 重复值
const e3: CardSize = 'big@small'; // 非法size

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 05:24:01