Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@cycle/dom 10.0.0-rc17 typing problems #307

Closed
wmaurer opened this issue May 9, 2016 · 24 comments
Closed

@cycle/dom 10.0.0-rc17 typing problems #307

wmaurer opened this issue May 9, 2016 · 24 comments

Comments

@wmaurer
Copy link

wmaurer commented May 9, 2016

I've come across a number of problems when building a new cycle / xstream based app using typescript.

  1. Cannot find module '@cycle/dom': the typings are not found at all by the typescript compiler.
    Solution: add the following line to @cycle/dom's package.json:
    "typings": "lib/index.d.ts"
  1. makeDOMDriver returns incorrect type Function. It should instead, return DriverFunction

  2. Too few interfaces are exported from index.d.ts. For example, I would like to use the interface DOMSource, so that I can define main as follows:

    interface Sources {
        DOM: DOMSource
    }

    function main(sources: Sources) {...}

This way, I would have edit-time intellisense in VSCode (or Atom with atom-typescript)
However, DOMSource is not exported from index.d.ts.

  1. DOMSource.events() returns any, which means the subsequent xstream methods and operators are not type checked. DOMSource.events() should have return type Stream<Event>

Having this issues fixed for the next RC would be very helpful.

@wmaurer
Copy link
Author

wmaurer commented May 9, 2016

  1. The way that hyperscript-helpers has been written, with a list of functions based on an array of strings being created dynamically, doesn't lend itself to automatic creation of typings (see the resulting hyperscript-helpers.d.ts).

In this case, I believe that the typings would have to be written by hand, one for each function, e.g.:

    export function a(...params: any[]): Object;
    export function abbr(...params: any[]): Object;
    ...
  1. The snabdom custom typings are not landing in the lib folder, so:
    import { VNode } from 'snabbdom';

causes the typescript compiler to complain in lib/makeHTMLDriver.d.ts

  1. Not specific to @cycle/dom: I'm seeing numerous error messages relating to not finding require, Map, Promise, Array.from, etc. I'm compiling directly to ES5, using webpack and awesome-typescript-loader. I'm not sure if this is something specific to my setup ...

Let me know if I can supply more information, or if I can help out.

@TylorS
Copy link
Member

TylorS commented May 9, 2016

Thank you for all the reports. They will be investigated :)

@TylorS
Copy link
Member

TylorS commented May 9, 2016

Regarding 7 I've generally used typings install -SA es6-shim

@TylorS
Copy link
Member

TylorS commented May 9, 2016

Regarding 4 - events() has to return any, because it does not specifically return an xstream Stream since it does stream conversion, it could just as easily be an Rx Observable. I'd suggest using typecasting there.

@staltz
Copy link
Member

staltz commented May 9, 2016

Thanks wmaurer for the detailed reports. These are priority and we will fix them very soon

@wmaurer
Copy link
Author

wmaurer commented May 10, 2016

Regarding 4 - events() returning any:
I'm fighting against typescript's external module system to see if it's possible or feasible to have an additional set of typings (xstream specific) which would merge with with the existing @cycle/dom typings, thus providing an events() function which returns a Stream. This would take advantages of typescript's open ended interfaces capability. I'll let you know if something comes of this.

Another possibility would be to use typescript's generics, so that events() is defined as:

    events<T>(eventType: string, options: EventsFnOptions = {}): T<Event>

Usage would be:

    sources.DOM.select('.myinput').events<Stream>('input')
        .debug()

which is much nicer than:

    (sources.DOM.select('.myinput').events('input') as Stream<Event>)
        .debug()

@staltz
Copy link
Member

staltz commented May 10, 2016

Nice suggestions indeed!

@fenduru
Copy link

fenduru commented May 12, 2016

Just ran into this. The way I got around the lack of typings was to do:

import { run } from '@cycle/rxjs-run';
import { makeDOMDriver } from '@cycle/dom/src/index.ts';
import { DriverFunction } from '@cycle/base';
...
run(main, {
  DOM: (makeDOMDriver('body') as DriverFunction)
});

edit: that only got me so far before it complained about snabbdom

@ntilwalli
Copy link
Contributor

After being built, none of the individual tag hyperscript-helper functions are being exported in lib/hyperscript-helpers.d.ts (checked with 10.0.0-rc21) and I think it's because the d.ts files are being dynamically generated and functions that should be declared are also being dynamically generated and I don't think the compiler is smart enough to iterate on the properties of object exported as default. Seems like the tag helpers need to be explicitly listed...

Also those same tag helpers are currently exported from lib/index.d.ts but they're not imported in that file, so they point to nothing...

@wmaurer
Copy link
Author

wmaurer commented May 19, 2016

Nice suggestions indeed!

Regarding 4)

Unfortunately, my second suggestion won't work. I now see that Typescript doesn't yet support higher-kinded types.

I think the only way to do this is to supply sets of typings specifically for RxJS or xstream. But this implies that every driver would need a set of typings for each stream library, which is a bit of a pain ...

I do have a general suggestion regarding typings. Rather than exporting typings as classes, I would suggest exporting interfaces which describe the public API of the library.
DOMSource, for example, has some internal properties (_rootElement$, _runStreamAdapter) which can be seen in the public typings.
Instead, I would have DOMSource implement an IDOMSource**, which only has the public API:

export interface IDOMSource {
    select(selector: string): IDOMSource;
    events(eventType: string, options?: EventsFnOptions): any;
}
class DOMSource implements IDOMSource {...}

I believe this will help with using open-ended interfaces (which I don't think works with classes)

** I intentionally used the I prefix here to illustrate the point, but in general, prefixing interfaces with I is not recommended in the typescript world. Another naming convention could be better applied.

staltz added a commit to cyclejs/dom that referenced this issue May 25, 2016
@staltz
Copy link
Member

staltz commented May 25, 2016

@wmaurer I started solving these issues. Can you help clarify why and how did you perceive this problem?

  1. makeDOMDriver returns incorrect type Function. It should instead, return DriverFunction

As far as I can see, this shouldn't be perceived. Or is it a problem that Cycle.run should know how to receive any function as a driver?

@wmaurer
Copy link
Author

wmaurer commented May 25, 2016

@staltz thanks for starting to work on this

Cycle.run's second parameter is drivers: DriversDefinition, where DriversDefinition is typed as a hash of DriverFunction, which looks like:

export interface DriverFunction {
    (stream: any, adapter: StreamAdapter, driverName: string): any;
    streamAdapter?: StreamAdapter;
}

As a result, the typescript compiler gives me the following error:
image
(I see the same error when running tsc from the console)

If the intention is that Cycle.run should receive any function as a parameter, then its second parameter should no longer be a hash of DriverFunction, but rather:

run(main: (sources: any) => any, drivers: { [driverName: string]: Function }): DisposeFunction;

@staltz
Copy link
Member

staltz commented May 25, 2016

Yes, correct, thanks for the feedback, and I think your last paragraph is the right course of action.

@staltz
Copy link
Member

staltz commented May 28, 2016

@TylorS do you have an idea how to solve (6)?

@TylorS
Copy link
Member

TylorS commented May 28, 2016

I think we could have a reference tag to custom-typings/main.d.ts in the index.d.ts ?

@staltz
Copy link
Member

staltz commented May 28, 2016

@TylorS Ah yes. That's what's missing.

@mattiamanzati
Copy link

mattiamanzati commented May 30, 2016

@staltz Unfortunatelly this does not works, just installed 10.0.0-rc23 but when running tsc 1.8.10 I am getting

c:\Shared\XAMPP\htdocs\track>tsc
node_modules/@cycle/dom/lib/index.d.ts(1,1): error TS2654: Exported external package typings file cannot contain tripleslash references. Please contact the package author to update the package definition.
node_modules/@cycle/dom/lib/index.d.ts(6,10): error TS2304: Cannot find name 'a'.
... various html tags ...
node_modules/@cycle/dom/lib/index.d.ts(6,607): error TS2304: Cannot find name 'u'.
node_modules/@cycle/dom/lib/index.d.ts(6,610): error TS2304: Cannot find name 'ul'.
node_modules/@cycle/dom/lib/index.d.ts(6,614): error TS2304: Cannot find name 'video'.
node_modules/@cycle/dom/lib/isolateModule.d.ts(16,17): error TS2371: A parameter initializer is only allowed in a function or constructor implementation.
node_modules/@cycle/dom/lib/isolateModule.d.ts(19,18): error TS2371: A parameter initializer is only allowed in a function or constructor implementation.

c:\Shared\XAMPP\htdocs\track>

@staltz
Copy link
Member

staltz commented May 30, 2016

I'm working on it...

@staltz
Copy link
Member

staltz commented Jun 1, 2016

@wmaurer @fenduru @ntilwalli @mattiamanzati can you try and see if DOM 10.0.0-rc26 fixes your issues? All issues except number (4) should be fixed, and I put out an example using TypeScript: https://github.com/cyclejs/examples/tree/diversity/bmi-typescript

@mattiamanzati
Copy link

@staltz Yep! I confirm that with tsc or ts-loader fixes all the problems!

@staltz
Copy link
Member

staltz commented Jun 2, 2016

Ok, good news! I'll close this issue, but we can still comment here, of course. If we have more TS issues, we can open other issues.

@staltz staltz closed this as completed Jun 2, 2016
@TylorS TylorS removed the in progress label Jun 2, 2016
@wmaurer
Copy link
Author

wmaurer commented Jun 5, 2016

Hi @staltz, sorry for not replying earlier - been busy with family and work ...
Thanks for your work on this. It certainly has removed all the compile-time errors I was experiencing.

Do you have any ideas for fixing (4)? I could imagine having a some xstream specific typings for cycle/dom. I placed the following in my app's custom-typings folder, which solved my immediate problem:

import { IDOMSource, EventsFnOptions } from '@cycle/dom';
import { Stream } from 'xstream';

declare module '@cycle/dom' {
    export class DOMSource {
        select(selector: string): DOMSource;
        events(eventType: string, options?: EventsFnOptions): Stream<Event>;
    }
}

(... though to do this I really need EventsFnOptions to be exported by cycle/dom)

Should I open a new issue to continue discussing the possibilities to solve (4)?

@staltz
Copy link
Member

staltz commented Jun 5, 2016

Yes, lets open a new issue for that, and I have some ideas for solving it.

@wmaurer
Copy link
Author

wmaurer commented Jun 5, 2016

Ok, I'll kick it off ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants