Typescript class 方法 return 基于参数的类型

Typescript class method return type based on parameter

我正在尝试创建一个 class 方法,其 return 类型将取决于 标志参数 [=32= 的 boolean 值]

我在

时成功地做到了这一点
  • 使用实现接口的普通函数表达式,
  • 或在 class 中直接在 class 主体中声明方法重载时

但是,当我尝试使用由 class.

实现的接口时,我无法执行此操作

我想使用 class 方法的接口实现来实现动态 return 类型。

谢谢!

这里是示例代码,也可以在 Typescript Playground


// it works with interface for plain function
interface common {
  <T extends boolean>(flag: T): T extends true ? string : boolean ;
  (flag: boolean): string | boolean;
}
const method: common = (flag: boolean) => {
  if (flag) {
    return 'truhty';
  } else {
    return false ;
  }
}

// it works with plain method overload

function test(flag: true): string
function test(flag: false): boolean
function test(flag: boolean): string | boolean {
  if (flag) {
    return 'truthy'
  } else {
    return false;
  }
}

const x = test(true);
const y = test(false);

// This works with direct class method overload

class Exp {
  test(flag: true): string
  test(flag: false): boolean
  test(flag: boolean): string | boolean {
    if (flag) {
      return 'truthy'
    } else {
      return false;
    }
  }
}

const val = new Exp().test(false); // boolean!
const val2 = new Exp().test(true); // string!


// It does not work in class with interface overload
interface common2 {
  test(flag: true): string
  test(flag: false): boolean
  test(flag: boolean): string | boolean
}

class Exp2 implements common2 {
  test(flag: boolean) {
    if (flag) {
      return 'truthy'
    } else {
      return false;
    }
  }
}

// it is not working in class with generic conditional type

interface common3 {
  test<T extends boolean>(flag: T): T extends true ? string: boolean
  test(flag: boolean): string | boolean
}

class Exp3 implements common3 {
  test(flag: boolean) {
    if (flag) {
      return 'truthy';
    } else {
      return false;
    }
  }
}


const val3 = new Exp3().test(false); // WRONG false | 'truthy'!
const val4 = new Exp3().test(true); // WRONG false | 'truthy'!


// it does not work with conditional directly in class
class Exp4 {
  test<T extends boolean>(flag: T): T extends true ? string : boolean
  test(flag: boolean) {
    if (flag) {
      return 'truthy';
    } else {
      return false;
    }
  }
}

const val5 = new Exp3().test(false); // WRONG false | 'truthy'!
const val6 = new Exp3().test(true); // WRONG false | 'truthy'!

我认为您别无选择,只能在实现接口时在 class 中重复重载(就像您在 Exp 中所做的那样);这是一个修改后的 Exp2,它既实现了接口又列出了重载:

class Exp2 implements common2 {
  test(flag: true): string;
  test(flag: false): boolean;
  test(flag: boolean): string | boolean {
    if (flag) {
      return 'truthy'
    } else {
      return false;
    }
  }
}

Playground example

如果不这样做,则 class 方法与接口定义不匹配。该接口是您的 class 必须匹配的合同,而不是影响 class 声明的解释方式的蓝图。

我实际上找到了我一直在寻找的关于如何在带有接口的 class 方法上使用条件类型的答案。

您似乎可以使用具有条件泛型的接口,无需创建所有可能的重载,只要您键入实施.

所以根据我原来的 post,这将是:

type ResType<T extends boolean> = T extends true ? string : boolean;

interface common3 {
  test<T extends boolean>(flag: T): ResType<T>
}

class Exp3 implements common3 {
  test<T extends boolean>(flag: T): ResType<T> {
    if (flag) {
      return 'truthy' as ResType<T>;
    } else {
      return false as ResType<T>;
    }
  }
}


const val3 = new Exp3().test(false); // boolean
const val4 = new Exp3().test(true); //  string

Typescript Playground