admin管理员组文章数量:1430053
Typescript supports discriminated unions. How to extend the same concept with Rxjs to the filter
operator in below example?
interface Square {
kind: 'square';
width: number;
}
interface Circle {
kind: 'circle';
radius: number;
}
interface Center {
kind: 'center';
}
type Shape = Square | Circle | Center;
const obs$: Observable<Shape> = of<Shape>({ kind: 'square', width: 10 });
// Expected type: Observable<Square>
// Actual type: Observable<Shape>
const newObs$ = obs$.pipe(
filter((x) => x.kind === 'square')
);
I above code snippet, I would want to see newObs$ to have its type inferred as: Observable<Square>
. But apparently, TypeScript
doesn't do that.
How to achieve this? Am I reaching the limits of TypeScript type inference?
I look for this as it seems to be very useful in a Redux + Redux-Observable
codebase.
Typescript supports discriminated unions. How to extend the same concept with Rxjs to the filter
operator in below example?
interface Square {
kind: 'square';
width: number;
}
interface Circle {
kind: 'circle';
radius: number;
}
interface Center {
kind: 'center';
}
type Shape = Square | Circle | Center;
const obs$: Observable<Shape> = of<Shape>({ kind: 'square', width: 10 });
// Expected type: Observable<Square>
// Actual type: Observable<Shape>
const newObs$ = obs$.pipe(
filter((x) => x.kind === 'square')
);
I above code snippet, I would want to see newObs$ to have its type inferred as: Observable<Square>
. But apparently, TypeScript
doesn't do that.
How to achieve this? Am I reaching the limits of TypeScript type inference?
I look for this as it seems to be very useful in a Redux + Redux-Observable
codebase.
2 Answers
Reset to default 8Actually you can do this with TypeScript type guards. See section "Type Guards and Differentiating Types" at http://www.typescriptlang/docs/handbook/advanced-types.html
The key here is the function isWhatever(x: any): x is Whatever => ...
syntax.
This basically says that if the isWhatever
function returns true
then it guarantees that x
is of Whatever
type.
In your example TypeScript considers all three classes:
So you can define the predicate function for filter()
as this:
filter((x: Shape): x is Square => x.kind === 'square')
Now it will properly consider only the Square
class:
See live demo: https://stackblitz./edit/rxjs6-demo-z9lwxe?file=index.ts
Very similar question: https://github./ReactiveX/rxjs/issues/2340
This is not necessarily a limitation with the TypeScript type system but rather with the implementation of filter
. You can easily achieve the desired behaviour using flatMap
:
// Inferred type: Observable<Square>
const newObs$ = obs$.pipe(
flatMap((x) => x.kind === "square" ? of(x) : empty())
);
本文标签: javascriptTypescript discriminated union types with Rxjs filter operatorStack Overflow
版权声明:本文标题:javascript - Typescript discriminated union types with Rx.js filter operator? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745547977a2662795.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论