【问题标题】:Typescript class method return type based on parameter基于参数的Typescript类方法返回类型
【发布时间】:2022-11-04 23:19:13
【问题描述】:

我正在尝试使用其返回类型将取决于 boolean 值的方法创建一个类标志参数

我已经成功地做到了这一点

  • 使用实现接口的普通函数表达式,
  • 或在类中直接在类体中声明方法重载时

然而,当我尝试使用由该类实现的接口时,我无法做到这一点.

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

谢谢!

这是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'!

【问题讨论】:

    标签: typescript class dynamic interface return-type


    【解决方案1】:

    我认为您别无选择,只能在实现接口时重复类中的重载(就像您对 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

    如果不这样做,则类方法与接口定义不匹配。接口是您的类必须匹配的契约,而不是影响如何解释类​​的声明的蓝图。

    【讨论】:

    • 感谢那。我跳过了那个实现,因为我试图实现第一个示例中所做的事情,其中​​method 实现了common 接口而不声明所有重载。但我想这不能用类来完成。完成答案,这里是条件类型接口:tsplay
    • @mitsos1os - 啊,谢谢,没有意识到你想要两者。 :-)
    【解决方案2】:

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

    看来您可以使用带有条件泛型的接口,没有创造所有可能的重载,只要你类型从实现中转换返回值.

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

    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

    【讨论】:

    • 我认为您在那里使用了错误的游乐场链接。 :-) 但请注意,这不是打字回报,它正在使用类型断言在他们。只需键入它们就会看起来像 this 并且仍然会导致错误。类型断言有时是一种必要的邪恶,但它们绕过了类型检查(或多或少)。一般来说,最好避免它们。
    • 感谢您提及链接!我修好了它!你是对的,我写了打字虽然它实际上是铸造断言!有趣的是,即使在带有条件类型 createLabel 函数的实际 Typescript documentation 中,如果您看到引用的游乐场(在里面尝试按钮)并用实际实现替换throw unimplemented,它会产生与我相同的错误!哈哈哈TSPlay link
    • 几乎写了同样的问题,所以将我重定向到这里只是为了看到我已经想出了答案——除了我不满意,因为as ResType&lt;T&gt; 的两种类型转换。 :-/ 我想知道是否有办法在没有演员表的情况下制定这个。
    猜你喜欢
    • 2023-03-30
    • 2020-10-27
    • 2019-06-07
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 2021-07-18
    相关资源
    最近更新 更多