xstream icon indicating copy to clipboard operation
xstream copied to clipboard

Co/Contravariant stream subtypes

Open DylanRJohnston opened this issue 5 years ago • 1 comments

Hey Staltz, I was wondering if you'd be open to exporting two interface subtypes of Stream<A>, one that contains all of the methods that are contravariant in A maybe called Sink<A> and one that contains all of the methods that are covariant in A maybe called Source<A>. This would allow for proper subtyping of methods that are expecting source / sink streams as Stream<A> is currently invariant in A.

For example

export type ContravariantMethods = 'addListener' | 'removeListener' | 'subscribe'
export interface Sink<A> extends Pick<Stream<A>, ContravariantMethods> {}

Most of the covariant methods on Stream<A> are static, with the exception of remember and debug. So the Source type makes less sense.

DylanRJohnston avatar Nov 04 '19 07:11 DylanRJohnston

Example

/* Type 'Stream<3>' is not assignable to type 'Stream<number>'.
  Types of property '_ils' are incompatible.
    Type 'InternalListener<3>[]' is not assignable to type 'InternalListener<number>[]'.
      Type 'InternalListener<3>' is not assignable to type 'InternalListener<number>'.
        Type 'number' is not assignable to type '3'.
*/
const number$: xs.Stream<number> = xs.Stream.of(3 as const)
// Totally fine
const number$: xs.Sink<number> = xs.Stream.of(3 as const)

More concretely, we have a general event sink that expects events payloads of a certain generic structure, and then a system generating events with a more specific type, e.g. a string literal for the event type.

DylanRJohnston avatar Nov 04 '19 08:11 DylanRJohnston