You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript枚举映射类型兼容问题:Shape类型转换报错求解

解决TypeShape映射器类型不兼容问题

问题原因

你定义的mapper用Record<ShapeType, (shape: Shape) => void>做类型约束,导致每个绘制函数的参数被宽泛地限定为Shape联合类型,但实际drawPolygon只接受Polygon、drawRectangle只接受Rectangle。TypeScript无法保证传入的Shape就是对应子类型,因此抛出类型不兼容错误。同时原调用逻辑mapper[shape.type](shape)虽然逻辑自洽,但需要更精确的类型定义让TS识别匹配关系。

解决方案(TS 4.9+ 推荐)

利用可辨识联合特性,结合satisfies关键字约束映射器结构,同时保留精确的类型推断:

enum ShapeType {
  POLYGON = 'polygon',
  RECTANGLE = 'rectangle'
}

interface Polygon {
  type: ShapeType.POLYGON;
  points: Array<[number, number]>;
}

interface Rectangle {
  type: ShapeType.RECTANGLE;
  points: [[number, number], [number, number]];
}

type Shape = Polygon | Rectangle;

// 关联ShapeType与对应具体Shape类型
type ShapeMap = {
  [ShapeType.POLYGON]: Polygon;
  [ShapeType.RECTANGLE]: Rectangle;
};

// 定义映射器类型:每个键对应接受对应Shape子类型的函数
type ShapeHandlerMap = {
  [K in keyof ShapeMap]: (shape: ShapeMap[K]) => void;
};

const drawPolygon = (toDraw: Polygon): void => {};
const drawRectangle = (toDraw: Rectangle): void => {};

// 使用satisfies确保结构合规,同时保留精确类型推断
const mapper = {
  [ShapeType.POLYGON]: drawPolygon,
  [ShapeType.RECTANGLE]: drawRectangle
} satisfies ShapeHandlerMap;

const toDraw: Array<Shape> = [];
// TS自动识别shape.type与函数参数的匹配关系,无报错
toDraw.forEach((shape) => mapper[shape.type](shape));

低版本TS兼容方案

如果你的TS版本低于4.9(不支持satisfies),可以通过泛型函数辅助类型推断:

// 手动指定映射器类型
const mapper: ShapeHandlerMap = {
  [ShapeType.POLYGON]: (shape: Polygon) => drawPolygon(shape),
  [ShapeType.RECTANGLE]: (shape: Rectangle) => drawRectangle(shape)
};

// 泛型函数提取对应类型的Shape
function handleShape<K extends ShapeType>(shape: Extract<Shape, { type: K }>) {
  mapper[shape.type](shape);
}

const toDraw: Array<Shape> = [];
toDraw.forEach(handleShape);

原理说明

  • ShapeMap和ShapeHandlerMap将映射器的函数参数类型精确限定为对应子类型,避免了宽泛联合类型的不兼容问题。
  • 可辨识联合特性让TypeScript通过shape.type自动缩小shape的类型范围,确保调用时参数类型与函数要求完全匹配。

内容的提问来源于stack exchange,提问作者Léal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:07:14