TypeScript实现根据对象属性值动态匹配关联类型的方法
问题原因
你当前写法中,ApiFormats[Block.type]会被直接解析为TextApiFormat | ImageApiFormat的联合类型,无法和同对象下的block.type字段建立绑定关系,因此TS无法根据block.type的取值自动收窄apiFormat的类型,自然实现不了联动约束。
实现方案
核心思路是通过映射类型遍历所有合法的type值,为每个type单独生成匹配的结构,最终将所有结构组合为联合类型,利用TS的可辨识联合特性实现字段联动。
完整实现代码:
type TextApiFormat = { title: string } type ImageApiFormat = { src: string } export type ApiFormats = { text: TextApiFormat image: ImageApiFormat } export type Block = { id: string type: keyof ApiFormats } // 联动类型核心实现 export type EditBlock = { [K in keyof ApiFormats]: { block: Block & { type: K } apiFormat: ApiFormats[K] } }[keyof ApiFormats]
实现效果
最终EditBlock会被推导为两个专属结构的联合类型:
- 当
block.type为text时,apiFormat自动匹配为TextApiFormat - 当
block.type为image时,apiFormat自动匹配为ImageApiFormat
使用时TS会自动做类型校验和收窄:
// 合法赋值无报错 const validTextBlock: EditBlock = { block: { id: '1', type: 'text' }, apiFormat: { title: '文本标题' } } // 类型不匹配时直接抛出错误 const invalidBlock: EditBlock = { block: { id: '2', type: 'image' }, apiFormat: { title: '错误的字段' // 此处TS报错:image类型不存在title字段 } } // 条件判断中自动收窄类型 function processBlock(editBlock: EditBlock) { if (editBlock.block.type === 'text') { // 此处TS自动推导apiFormat为TextApiFormat,可直接访问title console.log(editBlock.apiFormat.title) } else { // 此处TS自动推导apiFormat为ImageApiFormat,可直接访问src console.log(editBlock.apiFormat.src) } }
内容的提问来源于stack exchange,提问作者Calvein
相关产品推荐
相关产品推荐

