Giter VIP home page Giter VIP logo

Comments (5)

voliva avatar voliva commented on May 25, 2024 2

I think this is a limitation on Typescript rather than RxJS.

With TS 5.1 or before, you couldn't do the following:

const a = true;

// b is Array<number> | Array<string>
const b = a ? [1] : ['1'];

// TS 5.1
// Error: This expression is not callable.
b.filter(r => {});

Playground: https://www.typescriptlang.org/play?ts=5.1.6#code/FAYw9gdgzgLgBAQzgXjjATgVwKYG5iiSxwBGKicA-HANoCMAunAFy0DkdbD+wJAdADMAlgBsY2dAAp0KAHxwA3gF8AlPiA

This was fixed in TS 5.2 for Arrays in specific: https://devblogs.microsoft.com/typescript/announcing-typescript-5-2/#easier-method-usage-for-unions-of-arrays

The problem is that Typescript can't find compatible signatures when you have SomeType<A> | SomeType<B>. The workaround with arrays before 5.2 was to manually define the array type as an Array of the union:

const a = true;

const b: Array<number | string> = a ? [1] : ['1'];

// TS 5.1
// Now this works
b.filter(r => {});

And so your workaround is to do the same for observable. In your stackblitz you can try:

const tmp: Observable<undefined | null> = (a ? of(undefined) : of(null));
tmp.pipe(...)

And this will work. This is why from(a ? [undefined] : [null]) works: It returns an Observable<undefined | null> directly instead of a Observable<undefined> | Observable<null>

from rxjs.

benlesh avatar benlesh commented on May 25, 2024 1

I filed an issue upstream... because I agree it's confusing, but I'm not sure this is on us... microsoft/TypeScript#56741

We might have a pipe() overload with zero arguments that we could get rid of to provide better errors?

from rxjs.

rraziel avatar rraziel commented on May 25, 2024

I was wondering about the same thing, having a:

matchThingie(xx, {
  caseA: () => someObs,
  caseB: () => someOtherObs
}); // returns Observable<T> | Observable<U> so can't pipe

I figured I'd try to reproduce it (ok for like 5 minutes but still), adding pieces of the class one at a time but not having much luck, seems like TS is fine with it:

export interface OpFn<T, R> { (source: Observable<T>): Observable<R>; }
declare class Observable<T> {
  source: Observable<any> | undefined;
  operator: OpFn<any, T> | undefined;
  constructor(subscribe?: (this: Observable<T>, subscriber: unknown) => () => void);
  pipe(): Observable<T>;
  pipe<A>(op: OpFn<T, A>): Observable<A>;
  pipe<A, B>(op1: OpFn<T, A>, op2: OpFn<A, B>): Observable<B>;
  // all the other ones
}
declare const y: Observable<number> | Observable<string>;
y.pipe();
// sees all overloads, and somehow the one with no args always returns the first member of the union
// so if I swap number and string, pipe returns Observable<string> instead of Observable<number>

I'm not sure which part of the class makes TS think the other overloads can't be there
And as I see Ryan asked for a simpler reproduction, might not be that easy creating one 😅

from rxjs.

rraziel avatar rraziel commented on May 25, 2024

Actually went a bit further, seems to be the observer in the subscribe() that breaks it:

interface Unsubscribable { unsubscribe(): void; }
interface OperatorFunction<T, R> { (source: Observable<T>): Observable<R>; }
interface Observer<T> { next(value: T): void; }
declare class Observable<T> {
  pipe(): Observable<T>;
  pipe<A>(op: OperatorFunction<T, A>): Observable<A>;
  subscribe(observer: Partial<Observer<T>>): Unsubscribable;
}
declare const y: Observable<number> | Observable<string>;
y.pipe(); // only sees the first overload

from rxjs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.