【问题标题】:Typescript: Infering class members type打字稿:推断类成员类型
【发布时间】:2021-03-26 23:15:05
【问题描述】:

我有两种类型,它们的成员是一个名为“action”的函数。动作函数的参数类型取决于类:

type Class_a = {
    action: (arg: string) => string
} 
type Class_b = {
    action: (arg: number) => string
}

我想要一个可以处理这两个类的类。为此,我定义了一个联合类型:

type EitherClass = Class_a | Class_b;

我有一个类型可以根据类推断参数类型(如本答案所述:Have a Generic Type of a Method Depend on the Generic Type Of the Class in TypeScript

type ConditionalArg<T> = T extends Class_a ? string :
                         T extends Class_b ? number :
                         never;

但是,当我在另一个具有泛型类型的类中使用它时出现编译错误:

class MyClass<T extends EitherClass>
{
     public my_type: T;
     public my_arg: ConditionalArg<T>;

     public constructor(my_type: T, my_arg: ConditionalArg<T>)
     {
          this.my_type = my_type;
          this.my_arg = my_arg;
     }

     public do_action(): string
     {
          return this.my_type.action(this.my_arg); // Compile error here 
     }
} 

我收到以下错误: “ConditionalArg”类型的参数不能分配给“never”类型的参数。

调用构造函数时推理起作用

let inst_a: Class_a = {action: (arg: string) => arg}
let inst_b: Class_b = {action: (arg: number) => arg.toString()}

let class_a_one = new MyClass(inst_a, "B") // compile
let class_a_two = new MyClass(inst_a, 3)  // do not compile
let class_b_one = new MyClass(inst_b, "B") // do not compile
let class_b_two = new MyClass(inst_b, 3) // compile

但是,推理在“do_action”方法中不起作用。是否有避免该错误的解决方法?

这是操场上的一个工作示例:Playground Link

【问题讨论】:

  • 以下是否足够好? typescriptlang.org/play?#code/…
  • 确实有效。但是,就我而言,我无法修改 Class_a 和 Class_b,所以我无法将它们替换为使用泛型的类...
  • 您不必修改 Class_a - 您可以依靠结构等价性(您的示例中是否显示了整个 class_a。不同的论点是否是 class_a 和 class_b 之间的唯一区别?)
  • 不,class_a 有几个其他成员,class_b 也有。他们的成员有些是共同的,有些是不同的。

标签: typescript generics conditional-types


【解决方案1】:

我终于找到了解决方法。这个想法是在“do_action()”中强制转换“action”函数:

public do_action(): string
{
     let action = this.my_type.action as (arg: ConditionalArg<T>) => string
     return action(this.my_arg); // compile
}

操场上的工作示例:Playground link

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-09
    • 2018-08-12
    • 2020-04-02
    • 2020-12-20
    • 2016-08-03
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多