如何用TypeScript映射与条件类型实现TypeORM递归Relations类型
TypeORM Relations 泛型类型正确实现
问题分析
原实现存在三个核心逻辑错误:
- 键筛选逻辑错误,对键名本身做实体判断,而非判断键对应的属性值类型
- 未将关联键标记为可选,不符合「部分或全部属性」的要求
- 处理数组类型关联时未提取元素类型,导致嵌套Relations类型传入错误的泛型参数
正确实现代码
import type { BaseEntity } from "typeorm"; // 工具类型:提取数组元素类型,非数组类型直接返回本身 type Flatten<T> = T extends Array<infer ItemType> ? ItemType : T; // 工具类型:提取实体T中所有属性值为实体/实体数组的键 type EntityRelationKeys<T extends BaseEntity> = { [Key in keyof T]: Flatten<T[Key]> extends BaseEntity ? Key : never; }[keyof T]; // 最终要求的Relations泛型类型 type Relations<T extends BaseEntity> = { [Key in EntityRelationKeys<T>]?: Relations<Flatten<T[Key]>>; };
效果验证
该实现完全匹配给出的所有校验规则:
- 仅允许传入实体本身存在的、属性值为实体/实体数组的键,其他键都会触发类型错误
- 键对应的值必须是对应实体类型的Relations类型,不匹配就会报错
- 支持无限层级的嵌套关联定义,完全符合TypeORM关联查询的参数类型要求
内容的提问来源于stack exchange,提问作者Utku
相关产品推荐
相关产品推荐

