本文介绍如何在 TypeScript 中定义一个泛型条件接口 IGeometry<T>,使其 shape 属性的类型严格依赖于同接口中 geometryType 的具体枚举值,实现类型安全的几何对象建模。
本文介绍如何在 typescript 中定义一个泛型条件接口 `igeometry`,使其 `shape` 属性的类型严格依赖于同接口中 `geometrytype` 的具体枚举值,实现类型安全的几何对象建模。
在构建地理信息系统(GIS)、图形渲染或空间数据处理类库时,我们常需对多种几何类型(如圆形、多边形、点、椭圆)进行统一建模,同时保证每个实例的结构与类型声明完全匹配——即:当 geometryType 为 CIRCLE 时,shape 必须是 ICircle,且不能被误赋为 IPolygon 等其他类型。TypeScript 原生不支持“运行时值驱动编译时类型”,但可通过泛型约束 + 分布式条件类型优雅实现该需求。
核心思路是将 geometryType 的具体值作为泛型参数 T 传入接口,再利用条件类型(T extends X ? Y : Z)逐级推导 shape 的精确类型:
export enum GeometryType { CIRCLE = 4, POLYGON = 5, POINT = 6, ELLIPSE = 7}export interface ICircle { center: number; radius: number;}export interface IPolygon { lat: number; lon: number;}export interface IPoint { lat: number; lon: number;}export interface IEllipse { yAxis: number; xAxis: number; angle: number;}// ✅ 条件接口:shape 类型由 geometryType 的泛型实参决定export interface IGeometry<T extends GeometryType> { geometryType: T; shape: T extends GeometryType.CIRCLE ? ICircle : T extends GeometryType.POLYGON ? IPolygon : T extends GeometryType.POINT ? IPoint : T extends GeometryType.ELLIPSE ? IEllipse : never; // 防御性兜底:非法 T 值导致 shape 为 never,强制编译报错}
使用时,显式指定泛型参数即可获得强类型保障:
// ✅ 正确:geometryType 和 shape 完全匹配,无类型错误const circle: IGeometry<GeometryType.CIRCLE> = { geometryType: GeometryType.CIRCLE, shape: { center: 0, radius: 5 }};const polygon: IGeometry<GeometryType.POLYGON> = { geometryType: GeometryType.POLYGON, shape: { lat: 10.0000, lon: -10.0000 }};// ❌ 编译错误:类型不兼容(若取消注释将触发 TS2322)// const invalid: IGeometry<GeometryType.CIRCLE> = {// geometryType: GeometryType.CIRCLE,// shape: { lat: 0, lon: 0 } // Error: Type 'IPoint' is not assignable to type 'ICircle'// };
⚠️ 注意事项:
通过该模式,你不仅实现了“一值定型”的接口契约,更将类型系统转化为领域建模的主动约束工具——让错误在编码阶段暴露,而非运行时崩溃。