首页 > 解决方案 > TypeScript 条件类型的类在结构上是等效的

问题描述

我有以下内容:

declare class Base {
  constructor(a: string)
}

declare class A extends Base {
  constructor(a: number)
}

declare class B extends Base {
  constructor(a: object)
}

declare class C extends Base {
  constructor(a: boolean)
}

type ResponseMapper<T extends Base> = T extends A 
  ? number 
  : T extends B 
  ? object 
  : T extends C 
  ? boolean 
  : never;

declare function getValue<T extends Base>(input: T): ResponseMapper<T>

let x: number = getValue(new A(1))
let y: object = getValue(new B({}))
let z: boolean = getValue(new C(true))

TS游乐场

这并不完全有效,因为 A、B 和 C 在结构上都是等效的。所以 in ,如果我传递一个or inResponseMapper的实例,它仍然评估为。所以变量声明最终成为类型错误。BCnumberyz

我想出一种解决方法是为每个类添加一个假属性,使类型在结构上不再等效。所以这有效:

declare class Base {
  constructor(a: string)
}

declare class A extends Base {
  _name?: "A"
  constructor(a: number)
}

declare class B extends Base {
  _name?: "B"
  constructor(a: object)
}

declare class C extends Base {
  _name?: "C"
  constructor(a: boolean)
}

type ResponseMapper<T extends Base> = T extends A 
  ? number 
  : T extends B 
  ? object 
  : T extends C 
  ? boolean 
  : never;

declare function getValue<T extends Base>(input: T): ResponseMapper<T>

let x: number = getValue(new A(1))
let y: object = getValue(new B({}))
let z: boolean = getValue(new C(true))

TS游乐场

有没有更好的方法来让它工作而不需要添加一个假字段?

标签: typescript

解决方案


在这里,尝试使用这种类型:

type ResponseMapper<T, U> = T extends new (a: infer R) => U ? R : never;

declare function getValue<T extends new (a: V) => U, U, V = ResponseMapper<T, U>>(input: U): V;

TS游乐场


推荐阅读