TypeScript接口条件属性配置:按需必填属性实现方案咨询
条件式必填Props的TypeScript实现方案
我正在开发一个根据页面动态切换区块的组件,当前定义的Props接口如下:
interface Props { heading: string; description: string; signUp?: boolean; signUpButton1?: string; signUpButtonLink1?: string; signUpButton2?: string; signUpButtonLink2?: string; startFreeAccount?: boolean; startFreeAccountSignUpButton?: string; startFreeAccountLink1?: string; startFreeAccountSignUpLink1?: string; startFreeAccountSignUpLink2?: string; startFreeAccountSignUpLink3?: string; contactUsForDemo?: boolean; contactUsForDemoInput1?: string; contactUsForDemoInput2?: string; contactUsForDemoInput3?: string; contactUsForDemoButtonText?: string; ThanksForDemo?: boolean; ThanksForDemoButton?: string; }
代码里通过props.signUp &&渲染对应区块,但遇到两个矛盾的问题:
- Next.js的Link组件无法接收
undefined类型的链接属性 - 如果把这些关联属性设为必填,即使不启用signUp区块,也必须传入对应值,不符合动态切换的逻辑
需要实现的效果是:当某个布尔开关(比如signUp === true)启用时,对应的关联属性(signUpButton1、signUpButtonLink1等)必须赋值;开关关闭或不填时,这些属性无需传入。
解决方案:用TypeScript联合类型实现条件校验
核心思路是把Props拆分为基础必填属性和各区块的启用/关闭子类型,再通过联合类型组合,让TypeScript自动校验不同场景下的属性必填性。
1. 拆分基础属性与各区块的子类型
先定义所有场景都需要的基础属性,再分别定义每个区块启用/关闭时的属性规则:
// 所有场景都必填的基础属性 interface BaseProps { heading: string; description: string; } // SignUp区块启用时的属性:开关为true,关联必填属性设为必填 interface SignUpEnabledProps { signUp: true; signUpButton1: string; signUpButtonLink1: string; signUpButton2?: string; // 可选属性保持原规则 signUpButtonLink2?: string; } // SignUp区块关闭时的属性:开关为false/不填,关联属性设为never(禁止传入) interface SignUpDisabledProps { signUp?: false; signUpButton1?: never; signUpButtonLink1?: never; signUpButton2?: never; signUpButtonLink2?: never; } // StartFreeAccount区块的启用/关闭类型 interface StartFreeAccountEnabledProps { startFreeAccount: true; startFreeAccountSignUpButton: string; startFreeAccountLink1: string; startFreeAccountSignUpLink1: string; startFreeAccountSignUpLink2: string; startFreeAccountSignUpLink3: string; } interface StartFreeAccountDisabledProps { startFreeAccount?: false; startFreeAccountSignUpButton?: never; startFreeAccountLink1?: never; startFreeAccountSignUpLink1?: never; startFreeAccountSignUpLink2?: never; startFreeAccountSignUpLink3?: never; } // ContactUsForDemo区块的启用/关闭类型 interface ContactUsForDemoEnabledProps { contactUsForDemo: true; contactUsForDemoInput1: string; contactUsForDemoInput2: string; contactUsForDemoInput3: string; contactUsForDemoButtonText: string; } interface ContactUsForDemoDisabledProps { contactUsForDemo?: false; contactUsForDemoInput1?: never; contactUsForDemoInput2?: never; contactUsForDemoInput3?: never; contactUsForDemoButtonText?: never; } // ThanksForDemo区块的启用/关闭类型 interface ThanksForDemoEnabledProps { ThanksForDemo: true; ThanksForDemoButton: string; } interface ThanksForDemoDisabledProps { ThanksForDemo?: false; ThanksForDemoButton?: never; }
2. 组合成最终的Props类型
通过交叉类型(&)将基础属性与各区块的联合类型(|)组合:
type Props = BaseProps & (SignUpEnabledProps | SignUpDisabledProps) & (StartFreeAccountEnabledProps | StartFreeAccountDisabledProps) & (ContactUsForDemoEnabledProps | ContactUsForDemoDisabledProps) & (ThanksForDemoEnabledProps | ThanksForDemoDisabledProps);
效果说明
- 当你设置
signUp: true时,TypeScript会强制要求传入signUpButton1和signUpButtonLink1,避免undefined传入Link组件 - 当
signUp设为false或不填时,无法传入signUpButton1等关联属性(传入会触发类型报错),符合动态切换的逻辑 - 其他区块的布尔开关和关联属性会遵循同样的校验规则
内容的提问来源于stack exchange,提问作者Tihi
相关产品推荐
相关产品推荐

