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

TypeScript工厂函数返回可辨识联合类型报错如何解决?

问题原因

TypeScript 目前暂不支持在泛型函数内部,对依赖泛型参数的条件类型返回值做类型自动窄化。你代码里的DiscriminateUnion<Shape, 'kind', T>是依赖泛型T的条件类型,即使你通过switch分支判断了shapeKind的具体值,编译器也无法将泛型T和当前分支的具体字符串字面量类型做绑定,因此判定返回的Circle/Square实例和返回值类型不匹配,抛出以下错误:

Type 'Circle' is not assignable to type 'DiscriminateUnion<Circle, "kind", T> | DiscriminateUnion<Square, "kind", T>'.
Type 'Circle' is not assignable to type 'DiscriminateUnion<Square, "kind", T>'.(2322)

解决方案

以下是两种常见的修复方式:

方案1:使用函数重载(更推荐,类型提示更直观)

直接为不同入参声明对应的返回类型,复杂的泛型条件类型都可以省略:

type ShapeKind = 'circle' | 'square'

class Circle{
  kind: "circle" = 'circle';
  radius: number;
  constructor() {
    this.radius = 4
  }
}

class Square{
  kind: "square" = 'square';
  sideLength: number;
  constructor() {
    this.sideLength = 4
  }
}

type Shape = Circle | Square;

// 函数重载声明
function makeShape(shapeKind: 'circle'): Circle
function makeShape(shapeKind: 'square'): Square
// 函数实现
function makeShape(shapeKind: ShapeKind): Shape {
    switch (shapeKind) {
        case 'circle':
            return new Circle()
        case 'square':
            return new Square()
        default:
        throw Error('not valid shape')
    }
}

const newSquare = makeShape('square') // 编译器自动识别为Square类型
const newCircle = makeShape('circle') // 编译器自动识别为Circle类型

方案2:添加类型断言(改动最小)

你的业务逻辑本身是正确的,只是编译器无法自动推导类型匹配关系,所以可以手动给返回值加上类型断言,告知编译器类型符合预期:

type ShapeKind = 'circle' | 'square'

class Circle{
  kind: "circle" = 'circle';
  radius: number;
    constructor() {
        this.radius = 4
    }
}

class Square{
  kind: "square" = 'square';
  sideLength: number;
      constructor() {
        this.sideLength = 4
    }
}

type Shape = Circle | Square;

type DiscriminateUnion<T, K extends keyof T, V extends T[K]> =
  T extends Record<K, V> ? T : never

function makeShape<T extends ShapeKind>(shapeKind: T): DiscriminateUnion<Shape, 'kind', T> {
    switch (shapeKind) {
        case 'circle':
            // 手动添加类型断言
            return new Circle() as DiscriminateUnion<Shape, 'kind', T>
        case 'square':
            // 手动添加类型断言
            return new Square() as DiscriminateUnion<Shape, 'kind', T>
        default:
        throw Error('not valid shape')
    }
}

const newSquare = makeShape('square')

内容的提问来源于stack exchange,提问作者ghclark2

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 02:18:02