【问题标题】:Typescript RXjs version 6.6.0, issue with typing in subscriptionTypescript RXjs 版本 6.6.0,输入订阅时出现问题
【发布时间】:2021-08-03 16:43:48
【问题描述】:

已尝试以下语法:

   const s1 = new subject()

    s1.subscribe({
        next: (value) => {},
        error: (value) => {},
        complete: (value) => {},
    });

我收到以下错误:

编译失败。

src/app/services/data/data-bank-service/data-bank.service.ts:40:57 - 错误 TS2554:预期有 2-3 个参数,但得到了 1 个。

40
s1.订阅({ ~~~~~~~~~~~ 41下一个:(值)=> {}, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ... 43完成:(值)=> {}, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 44 }); ~~~~~~~~~~

node_modules/rxjs/internal/Observable.d.ts:51:39 51 subscribe(next: null | undefined, error: (error: any) => void, complete?: () => void): 订阅; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 未提供“错误”的参数。

现在我知道传入回调有一种新语法

subscribe(callback, callback ,callback)subscribe({next: callback, error: callback, complete: callback})

但我似乎无法正确实施它。有什么建议吗?

来自网站的示例

http://reactivex.io/rxjs/manual/overview.html#subject

【问题讨论】:

  • 可能是因为complete 没有收到任何值,应该只是complete: () => {},。如果没有,则创建一个可重现的演示。
  • @martin 原来是这样,谢谢没有考虑到这一点!

标签: angular typescript rxjs


【解决方案1】:

martin 在comment 中正确指出罪魁祸首是complete 的错误类型:它应该是() => void,而不是(value: unknown) => void

我想解释一下为什么会以这种方式显示错误。

有问题的方法subscribe 是带有重载签名的implemented in RxJS

  subscribe(observer?: PartialObserver<T>): Subscription;
  /** @deprecated Use an observer instead of a complete callback */
  subscribe(next: null | undefined, error: null | undefined, complete: () => void): Subscription;
  /** @deprecated Use an observer instead of an error callback */
  subscribe(next: null | undefined, error: (error: any) => void, complete?: () => void): Subscription;
  /** @deprecated Use an observer instead of a complete callback */
  subscribe(next: (value: T) => void, error: null | undefined, complete: () => void): Subscription;
  subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription;

当你调用这个方法时,TypeScript 按顺序(从上到下)查看重载。

OP 试图传入的对象是

{
  next: (value) => {},
  error: (value) => {},
  complete: (value) => {},
}

最初推断其签名如下。

{
  next: (value: unknown) => void,
  error: (value: unknown) => void,
  complete: (value: unknown) => void,
}

只有在类型检查器在subscribe 方法中找到此参数的匹配重载之后(并且如果),才会推断unknowns 的预期类型。

当 Typescript 尝试这样做时,它会检查第一个签名。它接受PartialObserver,基本上是

{
  closed?: boolean;
  next?: (value: T) => void;
  error?: (err: any) => void;
  complete?: () => void;
}

必须至少存在nexterrorcomplete 之一(有关详细信息,请参阅here)。

但是 OP 提供的对象不适合,因为 complete 的类型错误。 TypeScript 在某些版本中默默地忽略这个,并跳到下一个重载。我强调这一点,因为这是造成混乱的关键。

随着 TypeScript 不断下降,由于不同的原因,它无法匹配不同的签名。在不知道 OP 使用的确切 TS 版本的情况下,无法判断错误将如何准确报告。 When I run a similar example in 4.2.3,我得到错误 TS2769,它比 OP 得到的 TS2554 更清晰:

No overload matches this call.
  Overload 1 of 5, '(observer?: PartialObserver<unknown> | undefined): Subscription', gave the following error.
    Type '(value: any) => void' is not assignable to type '() => void'.
  Overload 2 of 5, '(next?: ((value: unknown) => void) | undefined, error?: ((error: any) => void) | undefined, complete?: (() => void) | undefined): Subscription', gave the following error.
    Argument of type '{ next: (value: unknown) => void; error: (value: any) => void; complete: (value: any) => void; }' is not assignable to parameter of type '(value: unknown) => void'.
      Object literal may only specify known properties, and 'next' does not exist in type '(value: unknown) => void'.

它仍然不完美,因为它并没有真正解释为什么重载 3、4 和 5 会失败,但它可以在未来改进。

要点:如果错误对您没有意义,请尝试查看其他重载是什么,并自己按顺序“评估”它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-20
    • 1970-01-01
    • 2022-09-28
    • 2019-12-04
    • 2021-12-30
    • 2020-09-20
    • 1970-01-01
    • 2021-12-07
    相关资源
    最近更新 更多