TypeScript条件联合类型创建:格式化参数类型约束实现方案
解决方案:使用可区分联合类型实现字段约束
要实现你需要的按numberType区分字段约束的需求,可区分联合类型(Discriminated Union)是最精准的方案。它通过共用的判别式字段(这里就是numberType),让TypeScript自动推断不同分支下的字段类型,完全符合你的要求:
步骤1:拆分定义不同类型的参数结构
先把参数拆分为「数值类参数」和「日期类参数」,再通过联合类型合并:
// 提取所有类型共用的基础字段 type BaseFormatParams = { formatKey: number; }; // 数值类型(General/Percent/$)对应的参数约束 type NumericFormatParams = BaseFormatParams & { numberType: 'General' | 'Percent' | '$'; magnitudeTruncation: 0 | 1 | 2; decimalPlaces: 0 | 1 | 2; }; // 日期类型对应的参数约束 type DateFormatParams = BaseFormatParams & { numberType: 'Date'; magnitudeTruncation: null; decimalPlaces: null; }; // 最终的联合类型,替代原来的单一接口 export type FormatOutputParameters = NumericFormatParams | DateFormatParams;
步骤2:编写类型守卫函数(可选但实用)
如果需要在业务代码中快速判断参数类型,可以写类型守卫函数,让TypeScript在分支中自动推断字段:
// 判断是否为数值类型参数 function isNumericFormatParams(params: FormatOutputParameters): params is NumericFormatParams { return ['General', 'Percent', '$'].includes(params.numberType); } // 判断是否为日期类型参数 function isDateFormatParams(params: FormatOutputParameters): params is DateFormatParams { return params.numberType === 'Date'; }
步骤3:实际使用示例
在业务逻辑中,TypeScript会根据numberType自动约束字段的取值:
function processFormat(params: FormatOutputParameters) { if (isDateFormatParams(params)) { // 此处params被推断为DateFormatParams,magnitudeTruncation和decimalPlaces必为null console.log('处理日期格式化,忽略量级和小数位参数'); } else { // 此处params被推断为NumericFormatParams,两个字段只能是0/1/2 console.log(`处理数值格式化:保留${params.decimalPlaces}位小数,截断到${params.magnitudeTruncation}级`); } } // 合法的参数示例 const validDateParams: FormatOutputParameters = { formatKey: 1, numberType: 'Date', magnitudeTruncation: null, decimalPlaces: null }; const validNumericParams: FormatOutputParameters = { formatKey: 2, numberType: 'Percent', magnitudeTruncation: 1, decimalPlaces: 2 }; // 非法参数会被TypeScript报错 const invalidParams: FormatOutputParameters = { formatKey: 3, numberType: 'Date', magnitudeTruncation: 0, // 报错:类型"0"不能赋值给类型"null" decimalPlaces: null };
这种方案的核心是利用numberType作为判别式,让TypeScript能精准识别不同分支下的字段结构,既满足了类型约束,又保证了代码的可读性和安全性。
内容的提问来源于stack exchange,提问作者arunmmanoharan
相关产品推荐
相关产品推荐

