TypeScript:实现含可选never值的类型工具及条件属性禁用
解决方案:根据属性值完全禁用指定属性
你遇到的核心问题是key?: never的行为和预期不符——TypeScript中key?: never等价于key?: undefined,允许显式传递undefined,但你需要的是完全禁止该属性出现在传入参数中。
要实现“根据另一个属性的取值控制是否允许传递某个属性”,可以通过互斥联合类型实现,让不同分支的类型分别对应允许/禁止目标属性的场景:
直接实现方案
interface BaseProps { lorem: string; } // 场景1:more为true时,必须传入ipsum(类型为string) type PropsWithIpsum = BaseProps & { more: true; ipsum: string; }; // 场景2:more为false或不传入时,完全不能出现ipsum属性 type PropsWithoutIpsum = BaseProps & { more?: false; }; // 最终的组件props类型 type LoremProps = PropsWithIpsum | PropsWithoutIpsum; export default function Lorem(props: LoremProps) { return <></>; } function Test() { return ( <> {/* ❌ 报错:ipsum不在PropsWithoutIpsum的属性列表中 */} <Lorem lorem="fndjsk" ipsum={undefined} /> {/* ✅ 正常:匹配PropsWithIpsum */} <Lorem lorem="fndjsk" more={true} ipsum="hfjdsk" /> {/* ✅ 正常:匹配PropsWithoutIpsum */} <Lorem lorem="fndjsk" /> {/* ✅ 正常:匹配PropsWithoutIpsum */} <Lorem lorem="fndjsk" more={false} /> </> ); }
封装成通用类型工具
如果需要复用这种“根据属性值控制其他属性”的逻辑,可以封装成通用类型:
/** * 通用条件属性控制类型 * @param Base - 基础属性类型 * @param Key - 用于判断的属性名 * @param Value - 触发允许目标属性的取值 * @param AllowedKeys - 当Key取Value时允许的属性列表 * @param ForbiddenKeys - 当Key不取Value时禁止的属性列表 */ type ConditionalProps< Base, Key extends keyof Base, Value extends Base[Key], AllowedKeys extends keyof any, ForbiddenKeys extends keyof any > = // 允许目标属性的分支:Key取Value,且包含AllowedKeys (Base & { [K in Key]: Value } & Record<AllowedKeys, any>) // 禁止目标属性的分支:排除ForbiddenKeys,且Key取非Value的值或不传入 | Omit<Base, Key | ForbiddenKeys> & { [K in Key]?: Exclude<Base[Key], Value> }; // 示例使用 interface Props { lorem: string; more?: boolean; } type LoremProps = ConditionalProps<Props, 'more', true, 'ipsum', 'ipsum'>;
为什么key?: never不生效?
TypeScript中,key?: never会被解析为key?: undefined,意味着该属性可以显式传递undefined,但不会禁止属性本身的出现。要完全禁止属性传递,必须让该属性在对应的类型分支中完全不存在(通过Omit或者不声明该属性实现)。
内容的提问来源于stack exchange,提问作者Audun Olsen
相关产品推荐
相关产品推荐

