xstream
xstream copied to clipboard
Co/Contravariant stream subtypes
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.
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.