bugfix> javascript > 投稿

タイプスクリプトのサポート差別された組合。Rxjsで同じ概念を filter に拡張する方法オペレーター 以下の例では?

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')
);

上記のコードスニペットでは、newObs $のタイプを次のように推測したいと考えています: Observable<Square> 。しかし、どうやら、 TypeScript それはしません。

これを達成する方法は? TypeScript型推論の制限に達しましたか?

Redux + Redux-Observable で非常に役立つように見えるので、私はこれを探しますコードベース。

回答 2 件
  • 実際には、TypeScriptタイプガードを使用してこれを行うことができます。 http://www.typescriptlang.org/docs/handbook/advanced-types.htmlのセクション「タイプガードとタイプの区別」を参照してください。

    ここで重要なのは function isWhatever(x: any): x is Whatever => ... です  構文。

    これは基本的に、 isWhatever  関数は true を返します  その後、それは x を保証します   Whatever のものです  タイプ。

    あなたの例では、TypeScriptは3つのクラスすべてを考慮します。

    したがって、 filter() の述語関数を定義できます  このように:

    filter((x: Shape): x is Square => x.kind === 'square')
    
    

    これで、 Square のみが適切に考慮されます。  クラス:

    ライブデモをご覧ください:https://stackblitz.com/edit/rxjs6-demo-z9lwxe?file=index.ts

    よく似た質問:https://github.com/ReactiveX/rxjs/issues/2340

  • これは、TypeScript型システムの制限ではなく、 filter の実装の制限です。 。 flatMap を使用して目的の動作を簡単に達成できます。 :

    // Inferred type: Observable<Square>
    const newObs$ = obs$.pipe(
      flatMap((x) => x.kind === "square" ? of(x) : empty())
    );
    
    

あなたの答え