#869·cyclejs

MockedDOMSource is not assignable to DOMSource

Author: ryota-kaCreated Dec 28, 2018Updated Jun 19, 2020

The release of @cycle/dom v22.2.0 seems to have resulted in introducing a breaking change, though it's a minor version bump.

In 90645d6, DOMSource has been rewritten to a union type, and MockedDOMSource is intentionally excluded from this union.

https://github.com/cyclejs/cyclejs/blob/c0bb763a56d74dba63a8ddee1113973b1b7bace3/dom/src/DOMSource.ts#L14-L16

Before this commit, it was defined as an interface, which allowed us to assign MockedDOMSource to DOMSource. https://github.com/cyclejs/cyclejs/blob/79344a4d288845bbb923a5548d8178681436971b/dom/src/DOMSource.ts#L11-L23

As a result, MockDOMSource is no longer assignable to DOMSource.


Additionally, it seems that we don't have any precise types to which both DOMSource and MockedDOMSource can be assign.

typescript
type Sources = { DOM: T }; // what should we expect for T?
type Sinks = { DOM: Stream<VNode> };

function Component(sources: Sources): Sinks {
    // ...
}

Of course we can define something like type T = DOMSource | MockedDOMSource, but this definition tsc will claim as following (as of typescript v3.2.2).

path/to/Component.ts:156:9 - error TS2347: Untyped function calls may not accept type arguments.

156         DOM.select('.incr')
            ~~~~~~~~~~~~~~~~~~~
157             .events('click')
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
158             .mapTo(1),
    ~~~~~~~~~~~~~~~~~~~~~~

To me, it appears that it is not a very good idea to define DOMSource as a union type, as TypeScript's inference over structual subtypes are not strong enough. (Or can it be possibly fixed with better typings?) If possible, it would be great that DOMSource is defined as an interface again, with enabling TypeScript's strict mode.

Thanks!