【问题标题】:ts(2454) Variable 'value' is used before being assignedts(2454) 变量“值”在被赋值之前被使用
【发布时间】:2020-07-06 08:20:07
【问题描述】:

对于以下代码(在严格模式下),我收​​到 typescript 编译时错误“在分配 ts(2454) 之前使用了变量‘值’”:

class Box<T> {
    constructor(private value: T) {
    }

    map<U>(f: (val: T) => U): Box<U> {
        return new Box<U>(f(this.value));
    }

    tap(f: (val: T) => unknown): void {
        f(this.value);
    }
}

function getValue<T>(box: Box<T>): T {
    let value: T;
    box.tap((val: T) => value = val);
    return value;
}

const multiplyByTwo = (value: number) => value * 2;
const box = new Box<number>(55).map(multiplyByTwo);
const val = getValue(box);
console.log(val);

错误是针对函数getValue的“返回值”行生成的。

TypeScript Playground

【问题讨论】:

  • 您好,如果您提供有关您想要实现的目标的提示,它可能会有所帮助。在当前代码中,您比编译器了解更多,因此会出现错误。我认为代码需要重构才能不抛出错误。
  • 嗨,代码 sn-p 是代码的简化版本,我尝试包装 ramda-fantay monad 以便通过装饰器模式对其进行扩展。特别是我添加了一个 getValue() 方法,该方法返回由 monad 封装的左/右值。
  • 编译器是对的。它可以看到变量value 被传递给box.tap() 的闭包使用,但它不知道box.tap() 对闭包有什么作用。执行代码时,getValue() 可以接收作为 box 的类的实例,该类扩展 Box 并以不同的方式实现 Box.tap()

标签: typescript


【解决方案1】:

我找不到优雅的解决方案。我只用@ts-ignore 注释标记了这一行。

【讨论】:

    【解决方案2】:

    我相信编译器没有被告知回调的作用((val: T) =&gt; unknown 在不运行代码的情况下不知道value = val)所以它不知道value 已设置。

    【讨论】:

      【解决方案3】:

      编译器不知道tap 回调实际上会在return value 行之前执行,所以它知道变量仍然有它的初始值undefined(不是T )。

      正确(和优雅)的解决方案不是滥用像 tap 这样的辅助函数来访问值,而是在类本身中放置一个适当的方法:

      class Box<T> {
          constructor(private value: T) {
          }
      
          map<U>(f: (val: T) => U): Box<U> {
              return new Box<U>(f(this.value));
          }
      
          getValue(): T {
              return this.value;
          }
      
          tap(f: (val: T) => unknown): Box<T> {
              f(this.getValue());
              return this;
          }
      }
      

      【讨论】:

      • 抱歉,Box 是一些我无法更改的第三方 api。
      • @sageagat 你应该在你的问题中更明确地说明这一点。你能链接那个Box API 的文档吗?据推测,它有比tap 更好的方法来访问该值。
      • 对此感到抱歉。正如我对@sunknudsen 所说,真正的代码是关于 ramda-fantasy 或者 monad link。我将它包装在一个装饰器类中以扩展它的功能。在装饰器内部,我有一个 getValue 方法,它尝试通过其任一方法访问 monad 的值。
      • @sageagat 您可能想要编辑您的问题以显示您的真实代码。您的 sn-p 中的 BoxEither 类还是自定义装饰器类?此外,either 方法的签名与tap 的签名非常不同,所以我不确定你在做什么。您绝对不需要在闭包中分配可变的value
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-08
      • 2019-01-16
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多