TypeScript如何基于现有类型将指定属性设为可选?
问题原因
直接用&编写交叉类型无法覆盖原有属性的必填/可选修饰符。TypeScript处理交叉类型的同名属性时,只会合并属性值的类型,不会覆盖可选性标记:BigLink中link本身是必填的string类型,即使交叉了{ link?: string },最终link属性还是会被判定为必填,不传入自然会抛出类型错误。
正确实现
使用TypeScript内置的Omit工具类型先移除BigLink中原有的link属性定义,再交叉自定义的可选link字段即可:
type OptionalBigLink = Omit<BigLink, 'link'> & { link?: string }
效果验证
使用上述类型定义变量时,不传link不会触发类型报错,传入link时也能正常校验类型:
// 合法:不传link无报错 const demo1: OptionalBigLink = { text: '无链接收藏项', some: 1, something: '测试内容1', else: '备注1' } // 合法:传入link符合string类型要求 const demo2: OptionalBigLink = { text: '带链接收藏项', link: '/home', some: 2, something: '测试内容2', else: '备注2' }
通用封装
如果后续经常需要把类型的指定字段改为可选,可以封装一个通用工具类型复用,不用每次都写Omit+交叉的逻辑:
// 把T类型中的K字段改为可选 type SetOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>> // 直接复用即可,效果和之前的写法完全一致 type OptionalBigLink = SetOptional<BigLink, 'link'>
如果需要把指定字段从可选改为必填,逻辑完全一致,只需要把工具类型里的
Partial替换为Required即可。
内容的提问来源于stack exchange,提问作者Hackerman
相关产品推荐
相关产品推荐

