如何为任意项数的逗号分隔字符串创建TypeScript类型?
问题描述
现有一个筛选值对象:
const values = { search, users, categories, sorting, }
需要派生一个名为FilterSelection的字符串类型,合法与非法示例如下:
const exampleFilterSelections = { valid: [ "all", "search,users,sorting", "-search", "-search,-users", ], invalid: [ "any", "search,-users", "users,users", "accounts", ] }
单个选项的类型容易定义:
type IncludedFilter = keyof typeof values type ExcludedFilter = `-${IncludedFilter}` // 注:原代码中SelectedFilter应为IncludedFilter
目标是定义FilterInclusions和FilterExclusions,从而组合出:
type FilterSelection = FilterInclusions | FilterExclusions | "all"
但当前手动枚举多组合的写法过于繁琐:
type FilterInclusions = | IncludedFilter | `${IncludedFilter},${IncludedFilter}` | `${IncludedFilter},${IncludedFilter},${IncludedFilter}` // 以此类推...
需要更简洁、非手动的实现方式。
解决方案
可以利用TypeScript的递归条件类型和字符串模板类型实现,同时确保:
- 仅包含合法筛选键(无未知项)
- 同一筛选键不重复出现
- 不会混合包含(无前缀)和排除(带
-前缀)的项
步骤1:修正并定义基础类型
// 补全values的实际值(示例用空字符串占位) const values = { search: "", users: "", categories: "", sorting: "", }; type IncludedFilter = keyof typeof values; type ExcludedFilter = `-${IncludedFilter}`;
步骤2:定义递归生成无重复组合的辅助类型
// 移除联合类型中的指定项,避免重复 type ExcludeFromUnion<T, U> = T extends U ? never : T; // 递归生成任意数量的唯一项逗号分隔字符串 type CommaSeparated<T extends string> = | T | `${T},${CommaSeparated<ExcludeFromUnion<T, T>>}`;
步骤3:生成FilterInclusions和FilterExclusions
type FilterInclusions = CommaSeparated<IncludedFilter>; type FilterExclusions = CommaSeparated<ExcludedFilter>;
步骤4:组合最终的FilterSelection
type FilterSelection = FilterInclusions | FilterExclusions | "all";
效果验证
此时以下场景会被正确校验:
- 合法:
"search"、"users,categories,sorting"、"-sorting,-search"、"all" - 非法:
"search,-users"(混合包含/排除)、"users,users"(重复项)、"accounts"(未知项)、"any"(非法关键字)
内容的提问来源于stack exchange,提问作者kaan_atakan
相关产品推荐
相关产品推荐

