属性 ‘positions’ 在类型上不存在

huangapple go评论99阅读模式
英文:

Property 'positions' does not exist on type

问题

I have this interface:

interface ScrollPositionRestore {
  event: Event;
  positions: { [K: number]: number };
  trigger: 'imperative' | 'popstate';
  idToRestore: number;
}

And this RxJS scan operator:

filter(
  (event) =>
    event instanceof NavigationStart || event instanceof NavigationEnd,
),
scan<Event, ScrollPositionRestore>((acc, event) => ({
  event,
  positions: {
    ...acc.positions,
    ...(event instanceof NavigationStart
      ? {
          [event.id]: this.contentArea.nativeElement.scrollTop,
        }
      : {}),
  },
  trigger:
    event instanceof NavigationStart
      ? event.navigationTrigger
      : acc.trigger,
  idToRestore:
    (event instanceof NavigationStart &&
      event.restoredState &&
      event.restoredState.navigationId + 1) ||
    acc.idToRestore,
})),

But I'm getting several TS errors:
属性 ‘positions’ 在类型上不存在

positions is declared on the ScrollPositionRestore interface, so why is TS not using that?

英文:

I have this interface:

interface ScrollPositionRestore {
  event: Event;
  positions: { [K: number]: number };
  trigger: &#39;imperative&#39; | &#39;popstate&#39;;
  idToRestore: number;
}

And this RxJS scan operator:

filter(
  (event) =&gt;
    event instanceof NavigationStart || event instanceof NavigationEnd,
),
scan&lt;Event, ScrollPositionRestore&gt;((acc, event) =&gt; ({
  event,
  positions: {
    ...acc.positions,
    ...(event instanceof NavigationStart
      ? {
          [event.id]: this.contentArea.nativeElement.scrollTop,
        }
      : {}),
  },
  trigger:
    event instanceof NavigationStart
      ? event.navigationTrigger
      : acc.trigger,
  idToRestore:
    (event instanceof NavigationStart &amp;&amp;
      event.restoredState &amp;&amp;
      event.restoredState.navigationId + 1) ||
    acc.idToRestore,
})),

But I'm getting several TS errors:
属性 ‘positions’ 在类型上不存在

positionsis declared on the ScrollPositionRestore interface, so why is TS not using that?

答案1

得分: 2

使用 scan 运算符可能有些棘手。累加器参数的类型将是累加器类型与源类型的并集,或者是累加器类型与种子类型(scan 的第二个参数)的并集。

由于您没有提供种子,acc 的类型被正确推断为 Event_2 | ScrollPositionRestore。语法错误出现,因为 positions 不是 Event_2 上的属性,因此不能存在于联合类型上。

为了解决这个问题,您应该重写对 scan 的调用并提供一个与累加器类型相同的种子。

filter(
  (event): event is NavigationStart | NavigationEnd => // I like my filters typed.
    event instanceof NavigationStart || event instanceof NavigationEnd,
),
scan<Event, ScrollPositionRestore, ScrollPositionRestore>((acc, event) => ({
  /* do the same assignment as before */
}), { positions: {} }) // <-- 种子

文档中并不清楚它是否以这种方式工作,但是如果您查看源代码,您会发现对提供种子的函数重载,当没有提供种子类型时,返回类型仅为累加器类型,当提供了种子类型时,返回类型为累加器类型和种子类型的并集。

英文:

Using the scan operator can be tricky. The type of the accumulator parameter will either the accumlator type unioned with the source type, or the accumlator type unioned with the type of the seed (the second parameter to scan).

Since you're not providing a seed, the type of acc is properly being inferred as Event_2 | ScrollPositionRestore. The syntax error appears, since positions is not a property on Event_2 and therefore cannot be on the unioned type.

To get around this you should rewrite the call to scan and provide a seed that's the same type as the accumlator type.

filter(
  (event): event is NavigationStart | NavigationEnd =&gt; // I like my filters typed.
    event instanceof NavigationStart || event instanceof NavigationEnd,
),
scan&lt;Event, ScrollPositionRestore, ScrollPositionRestore&gt;((acc, event) =&gt; ({
  /* do the same assignment as before */
}), { positions: {} }) // &lt;-- seed

It's not clear it works this way from the documentation, however if you look at the source, you'll see that for the function overloads that provide a seed, the return type is either just the accumulator type when no seed type is provided or the union of the accumulator and seed type when the seed type is provided.

huangapple
  • 本文由 发表于 2023年4月13日 20:19:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76005356.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定