如何用TypeScript定义含0-1个URI键值对的对象类型?
可行,具体实现方式如下
1. 定义URI的编译时类型约束
TypeScript无法通过类型系统完全覆盖所有URI格式规范,但可以用模板字面量类型做近似的编译时约束,比如匹配带协议的URI:
// 约束带协议的URI(如 http://xxx、https://xxx、ftp://xxx 等) type URI = `${string}://${string}`;
2. 实现符合要求的对象类型
要满足「0个或1个属性、键和值均为URI」的约束,可通过联合类型+交叉类型限制属性数量与类型:
// 单属性对象类型:键为URI,值为URI,且不允许额外属性 type SingleURIMap<K extends URI> = { [P in K]: URI } & { [P in Exclude<string, K>]?: never }; // 最终类型:空对象 或 符合要求的单属性对象 type URIMap = {} | SingleURIMap<URI>;
3. 编译时验证示例
// ✅ 合法:空对象 const emptyMap: URIMap = {}; // ✅ 合法:单个URI键+URI值 const validMap: URIMap = { "https://example.com": "https://api.example.com" }; // ❌ 非法:多个属性 const invalidMap1: URIMap = { "https://a.com": "https://b.com", "https://c.com": "https://d.com" }; // ❌ 非法:键不是URI const invalidMap2: URIMap = { "example.com": "https://api.example.com" }; // ❌ 非法:值不是URI const invalidMap3: URIMap = { "https://example.com": "api.example.com" };
4. 运行时补充校验
TypeScript类型约束仅在编译时生效,若涉及动态生成的对象(如API返回、用户输入),需添加运行时校验逻辑:
// 运行时校验字符串是否为URI function isURI(str: string): str is URI { // 可根据需求调整正则规则,这里是基础的URI匹配 const uriPattern = /^[a-zA-Z][a-zA-Z0-9+-.]*:\/\/.+/; return uriPattern.test(str); } // 运行时校验对象是否符合URIMap类型 function isValidURIMap(obj: unknown): obj is URIMap { if (typeof obj !== 'object' || obj === null) return false; const entries = Object.entries(obj); if (entries.length > 1) return false; if (entries.length === 0) return true; const [key, value] = entries[0]; return typeof value === 'string' && isURI(key) && isURI(value); }
内容的提问来源于stack exchange,提问作者gordie
相关产品推荐
相关产品推荐

