Typescript 类方法基于参数返回类型

发布于 2025-01-09 04:32:44 字数 3822 浏览 6 评论 0原文

我正在尝试创建一个类,其方法的返回类型将取决于 flag-parameterboolean 值,

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

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

表达式但是,当我尝试使用由类实现的接口时,我无法执行此操作

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

谢谢!

这是示例代码,也可在 打字稿游乐场


// 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'!

I am trying to create a class with a method whose return type will depend on the boolean value of a flag-parameter

I have managed to do this successfully when

  • using a plain function expression that implements an interface,
  • or in a class when declaring the method overloads directly in the class body

However, I am not able to do this when I am trying to use an interface that is implemented by the class.

I would like to do this using interface implementation for a class method to achieve the dynamic return type.

Thanks!

Here is the example code which is also available in the 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'!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

姐不稀罕 2025-01-16 04:32:44

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

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

I don't think you get a choice but to repeat the overload in the class (as you did with Exp) when implementing the interface; here's a modified Exp2 that both implements the interface and lists the overloads:

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

If you don't, the class method isn't a match for the interface definition. The interface is a contract your class must match, not a blueprint that affects how the class's declarations are interpreted.

焚却相思 2025-01-16 04:32:44

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

看来您可以使用带有条件泛型的接口,无需创建所有可能的重载,只要您类型从实现中转换返回值< /强>。

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

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

打字稿游乐场

I actually found the answer I was looking for on how to use conditional typing on a class method with an interface.

It seems that you can use the interface with its conditional generic, without creating all the possible overloads, as long as you type cast the returned values from the implementation.

So according to my original post, this would be:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文