英文:
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
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: '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
is 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 => // I like my filters typed.
event instanceof NavigationStart || event instanceof NavigationEnd,
),
scan<Event, ScrollPositionRestore, ScrollPositionRestore>((acc, event) => ({
/* do the same assignment as before */
}), { positions: {} }) // <-- 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论