TypeScript:如何让ICampaign接口的campaignTypeDetails字段可选且合规
解决TypeScript中ICampaign接口的类型关联与可选字段问题
问题根源
原来的单一接口定义中,campaignType和campaignTypeDetails是独立的联合类型,TypeScript无法建立两者的关联关系。当你指定campaignType: 'target-based'时,campaignTypeDetails只要满足TargetBasedCampaignDetailType | ViewBasedCampaignDetailType中的任意一个就会通过校验——比如你的示例中缺少gender的对象,其实匹配了ViewBasedCampaignDetailType的结构,所以没有触发错误。
解决方案:使用区分联合类型(Discriminated Union)
将ICampaign定义为联合类型,每个分支对应campaignType的具体取值,并关联对应的campaignTypeDetails类型,同时通过?标记该字段为可选。
修改后的完整代码:
interface CampaignDetailType { datetimeStart: string, datetimeEnd: string, devices: { id: number, }[], } interface TargetBasedCampaignDetailType extends CampaignDetailType { ageIntervals: { min: number, max: number }[], gender: "male" | "female" | "both" }; interface ViewBasedCampaignDetailType extends CampaignDetailType { }; // 定义为区分联合类型 type ICampaign = | { campaignType: "target-based"; // 标记为可选字段 campaignTypeDetails?: TargetBasedCampaignDetailType; example: string; } | { campaignType: "view-based"; // 标记为可选字段 campaignTypeDetails?: ViewBasedCampaignDetailType; example: string; };
效果验证
错误示例(会触发TypeScript校验错误)
当campaignType为target-based时,若campaignTypeDetails缺少gender字段,TypeScript会直接报错:
const invalidCampaign: ICampaign = { campaignType: 'target-based', campaignTypeDetails: { datetimeStart: "new Date()", datetimeEnd: "new Date()", devices: [{id:1}], ageIntervals: [] // 报错:缺少必填属性"gender" }, example: "" }
合法示例
// 1. target-based类型,省略campaignTypeDetails const validCampaign1: ICampaign = { campaignType: 'target-based', example: "test" }; // 2. target-based类型,包含完整的campaignTypeDetails const validCampaign2: ICampaign = { campaignType: 'target-based', campaignTypeDetails: { datetimeStart: "2024-01-01", datetimeEnd: "2024-01-31", devices: [{id: 1}], ageIntervals: [{min: 18, max: 30}], gender: "both" }, example: "test" }; // 3. view-based类型,包含campaignTypeDetails const validCampaign3: ICampaign = { campaignType: 'view-based', campaignTypeDetails: { datetimeStart: "2024-02-01", datetimeEnd: "2024-02-29", devices: [{id: 2}] }, example: "test" };
内容的提问来源于stack exchange,提问作者Muhammed Furkan CETINTAS
相关产品推荐
相关产品推荐

