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

Use more option types in the bindings? #21

Open
utkarshkukreti opened this issue Aug 4, 2019 · 5 comments
Open

Use more option types in the bindings? #21

utkarshkukreti opened this issue Aug 4, 2019 · 5 comments

Comments

@utkarshkukreti
Copy link

Is there any reason why functions which can return null in JS (e.g. document.querySelector) are not typed as returning option values? With the current types it's trivial to get runtime errors which I wouldn't expect from a statically typed language that compiles to JS. In TypeScript that function returns Element | null which means the user cannot call methods on it without checking that it's not null. In OCaml (BuckleScript) it returns Dom.element option. I would expect the same in F#.

cc @nojaf who suggested I open an issue here

@alfonsogarciacaro
Copy link
Member

It's true that Fable erases optional types and we do use option to represent things like Typescript optional members, but it's not always straightforward to use options to represent nullable types (there's a similar discussion here). In certain situations Fables does need to wrap Some values which will cause problems if you send the wrapped value to native JS code.

IIRC Typescript didn't have nullable types when we use the original declarations to generate the bindings, and I was using MDN documentation for the latest update. Moreover, nullable reference types are coming to F#, this may be a better opportunity to update the bindings with better compatibility and less breaking changes.

@utkarshkukreti
Copy link
Author

Ah, I didn't know about nullable types and isNull. Still seems weird that code written using fable-browser is less typesafe than even TypeScript (which I was hoping to replace with F#).

AFAIK BuckleScript guarantees that for Option<T> where T is not an Option itself, the representation of Some(T) == T and None == undefined. This makes it really convenient for 99% of the use cases (that I've encountered) and has no runtime overhead in most cases (when the compiler knows T is not an Option).

@alfonsogarciacaro
Copy link
Member

alfonsogarciacaro commented Aug 5, 2019

AFAIK BuckleScript guarantees that for Option where T is not an Option itself, the representation of Some(T) == T and None == undefined

Yes, it works more or less the same in Fable :) https://github.com/fable-compiler/Fable/blob/55904c4cf291df63287c1d2899b56b349e70f67f/src/Fable.Transforms/Transforms.Util.fs#L326-L331

If your primary target is to interact with JS in a type-safe way, I'd recommend using Typescript. This is a language created with that target as its main goal. Fable was created just to be able to program for the JS platform in F#. We try to make JS interop easier but you will still encounter many more friction points that when using Typescript.

@utkarshkukreti
Copy link
Author

Considering that ts2fable generates T option for T | undefined, is the only reason not to change these bindings in this repo to use option backward compatability? I'm wondering if I were to write my own bindings to querySelector which uses option, would that be incorrect?

If your primary target is to interact with JS in a type-safe way

Not exactly. I do use TypeScript for those use cases but I'm trying to decide between F# and OCaml (BuckleScript). I really like the syntax and features of F# but I'm still learning the ecosystem.

@alfonsogarciacaro
Copy link
Member

Sorry for the late reply, I somehow missed the notification of your last comment.

Yes, backward compatibility is a big factor as we had several breaking changes in latest release and this obviously annoys users. Also, if we were to make this change I'd like to wait a bit until nullable references come to F# (seems it'll happen soon) to see if they're a better fit for this case (although in Fable we'll probably still have issues with numbers and other value types, as they can also be null in JS).

I'm wondering if I were to write my own bindings to querySelector which uses option, would that be incorrect?

As mentioned above, it will probably work in 99% of cases, but Fable is wrapping options in a few cases as for generic parameters (because they may become nested options).

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

No branches or pull requests

2 participants