求助:如何实现Feature内部Geometry类型的通用Typeguard
通用GeoJSON Feature类型守卫实现
现有类型定义
工作中使用的GeoJSON相关TypeScript类型如下:
export type GeoJSON = Geometry | Feature; export type GeoJsonTypes = GeoJSON['type']; export interface GeoJsonObject { type: GeoJsonTypes; } export interface Point extends GeoJsonObject { type: 'Point'; coordinates: number[]; } export interface MultiPoint extends GeoJsonObject { type: "MultiPoint", coordinates: number[][]; } export type Geometry = | Point | MultiPoint export interface Feature<G extends Geometry = Geometry> extends GeoJsonObject { type: 'Feature'; geometry: G; }
问题场景
当前收窄Feature<Geometry>类型时,必须为每种Geometry对应的Feature编写单独的类型守卫,例如:
export function isPolygon(f: Feature): f is Feature<Polygon> { return f && f.geometry && f.geometry.type === 'Polygon'; }
尝试编写通用类型守卫时遇到类型错误:将泛型T约束为Feature会触发A type Predicate's type must be assignable to it's parameter type;约束为Geometry则会出现T could be instantiated with an arbitrary type which could be unrelated错误。
解决方案
调整泛型约束逻辑,直接针对Geometry的类型值做限定,即可实现合法的通用类型守卫:
export function isFeature<U extends Geometry['type']>( feature: Feature<Geometry>, type: U ): feature is Feature<Extract<Geometry, { type: U }>> { return !!feature && !!feature.geometry && feature.geometry.type === type; }
关键说明
- 泛型
U直接绑定到Geometry['type'],确保传入的type参数只能是合法的Geometry类型标识(如'Point'、'MultiPoint') - 参数
feature直接使用最宽泛的Feature<Geometry>类型,规避泛型参数T带来的类型兼容性冲突 - 通过
Extract工具类型从Geometry联合类型中筛选出对应type的具体类型,再包装为对应的Feature类型,保证类型断言的合法性
使用示例
const feature: Feature<Geometry> = {/* 任意Feature数据 */}; if (isFeature(feature, 'Point')) { // 此处feature类型自动收窄为Feature<Point> console.log(feature.geometry.coordinates); // 类型为number[] } if (isFeature(feature, 'MultiPoint')) { // 此处feature类型自动收窄为Feature<MultiPoint> console.log(feature.geometry.coordinates); // 类型为number[][] }
内容的提问来源于stack exchange,提问作者Martin Hansson
相关产品推荐
相关产品推荐

