-
Notifications
You must be signed in to change notification settings - Fork 6
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
Try to replace U2 arguments with overloads or common interfaces #1
Comments
Totally for this one :) It's how I update my bindings now and it's so much easier/natural to use |
ok I will refine my current WIP |
Question how do I transform this?
|
The error from F# is indeed "funny" when you do: type URL = int
type Test () =
static member fileURLToPath: string -> string = jsNative
static member fileURLToPath: URL -> string = jsNative Error:
So it's comparing only the number of arguments and the types... I would vote for using overload on And for I don't really know when Fable is generating the This is actually what I did to mock a function from export function icon(icon: IconName | IconLookup, params?: IconParams): Icon; module Exports =
open Fable.Core.JsInterop
type IconModule =
[<Emit("$0({iconName : $1, prefix: $2},Object.assign({}, $3))")>]
abstract Find: iconName: string * prefix: string * ?parameters: IconParams -> Icon
[<Emit("$0({iconName : $1, prefix: 'far'},Object.assign({}, $2))")>]
abstract FindRegular: icon: IconName * ?parameters: IconParams -> Icon
[<Emit("$0({iconName : $1, prefix: 'fas'},Object.assign({}, $2))")>]
abstract FindSolid: icon: IconName * ?parameters: IconParams -> Icon
[<Emit("$0({iconName : $1, prefix: 'fab'},Object.assign({}, $2))")>]
abstract FindBrand: icon: IconName * ?parameters: IconParams -> Icon
[<Emit("$0({iconName : $1, prefix: 'fal'},Object.assign({}, $2))")>]
abstract FindLight: icon: IconName * ?parameters: IconParams -> Icon
let icon : IconModule = importMember "@fortawesome/fontawesome-svg-core" And so like that, I am able to kind of mock the JavaScript API in a nice way for F# code. The emit is complex here this is to make the API even nicer to consume. |
hmm. why not. I'm going to try this. Thanks @MangelMaxime! |
Also, if the code looks ugly or is not possible to be supported. I guess we could only support one of the methods with an annotation stating it. For example, because we can pass an That's not perfect, but at least the user experience is still free of "hacks" like |
I agree with you! |
Hmm, why you need In any case if you need to use type Test () =
static member fileURLToPath(x: string): string = jsNative
static member fileURLToPath(x: URL): string = jsNative |
Oh I didn't know. If what @alfonsogarciacaro says is right then it's better than any hacks if we need |
I currently did that: module Static =
let domainToASCII: string -> string = importMember "url"
let domainToUnicode: string -> string = importMember "url"
let fileURLToPath: string -> string = importMember "url"
let fileURLToPathFromURL: URL -> string = importMember "url"
let pathToFileURL: string -> URL = importMember "url" The question I was asking myself this morning, was how to map static members for the Url type? So a type with static members and a single import * would work. But I had the overloading problem for fileURLToPath function. Honestly, I'm trying to make my way and there are a few things I quite don't grasp yet like the module.exports = {
// Original API
Url,
parse: urlParse,
resolve: urlResolve,
resolveObject: urlResolveObject,
format: urlFormat,
// WHATWG API
URL,
URLSearchParams,
domainToASCII,
domainToUnicode,
// Utilities
pathToFileURL,
fileURLToPath
}; How do I access the format member? Because there seems to be a trick there: there's actually the old format method which is available from the Url prototype. I guess that's the root of my current problem: format is found but the prototype I'm refering to in teh bindings is not what is really found in the .js source code. Again These are the kind of things I'm patiently learning ;) |
@whitetigle Which For url.format(urlObject) the following code works: // url.format({
// protocol: 'https',
// hostname: 'example.com',
// pathname: '/some/path',
// query: {
// page: 1,
// format: 'json'
// }
// });
//
// => 'https://example.com/some/path?page=1&format=json'
module URL =
type FormatOptions =
abstract member protocol : string with get, set
abstract member hostname : string with get, set
abstract member pathname : string with get, set
abstract member query : obj with get, set
let format (options : FormatOptions) : string = importMember "url"
let options =
jsOptions<URL.FormatOptions>(fun o ->
o.protocol <- "https"
o.hostname <- "example.com"
o.pathname <- "/some/path"
o.query <- createObj [
"page" ==> 1
"format" ==> "json"
]
)
let formattedURL = URL.format(options)
JS.console.log formattedURL
// Print: https://example.com/some/path?page=1&format=json |
Nope, the relatively new one. |
Ok, I have a working version which supports both Please note, that I wrote the binding from scratch without thinking if this is breaking the existant API and if this is easily scalable. // url.format({
// protocol: 'https',
// hostname: 'example.com',
// pathname: '/some/path',
// query: {
// page: 1,
// format: 'json'
// }
// });
//
// => 'https://example.com/some/path?page=1&format=json'
module URL =
type LegacyFormatOptions =
abstract member protocol : string with get, set
abstract member hostname : string with get, set
abstract member pathname : string with get, set
abstract member query : obj with get, set
type FormatOptions =
/// `true` if the serialized URL string should include the username and password, `false` otherwise. Default: `true`.
abstract member auth : bool with get, set
/// `true` if the serialized URL string should include the fragment, `false` otherwise. Default: `true`.
abstract member fragment : bool with get, set
/// `true` if the serialized URL string should include the search query, `false` otherwise. Default: `true`.
abstract member search : bool with get, set
/// `true` if Unicode characters appearing in the host component of the URL string should be encoded directly as opposed to being Punycode encoded. Default: `false`.
abstract member unicode : bool with get, set
type [<AllowNullLiteral>] URL =
abstract hash: string with get, set
abstract host: string with get, set
abstract hostname: string with get, set
abstract href: string with get, set
abstract origin: string
abstract password: string with get, set
abstract pathname: string with get, set
abstract port: string with get, set
abstract protocol: string with get, set
abstract search: string with get, set
// abstract searchParams: URLSearchParams // commented to make reproduction easier
abstract username: string with get, set
abstract toString: unit -> string
abstract toJSON: unit -> string
type IExports =
abstract member format : LegacyFormatOptions -> string
abstract member format : url : URL * ?options: FormatOptions -> string
[<Emit("new URL($1...)")>]
abstract Create: input:string -> URL
let url : URL.IExports = import "default" "url"
// Legacy code
let legacyOptions =
jsOptions<URL.LegacyFormatOptions>(fun o ->
o.protocol <- "https"
o.hostname <- "example.com"
o.pathname <- "/some/path"
o.query <- createObj [
"page" ==> 1
"format" ==> "json"
]
)
let formattedURL = url.format(legacyOptions)
JS.console.log formattedURL
// Print: https://example.com/some/path?page=1&format=json
// New code
// const myURL = new URL('https://a:b@測試?abc#foo');
// console.log(myURL.href);
// // Prints https://a:b@xn--g6w251d/?abc#foo
// console.log(myURL.toString());
// // Prints https://a:b@xn--g6w251d/?abc#foo
// console.log(url.format(myURL, { fragment: false, unicode: true, auth: false }));
// // Prints 'https://測試/?abc'
let myUrl = url.Create("https://a:b@測試?abc#foo")
JS.console.log myUrl.href
// Prints https://a:b@xn--g6w251d/?abc#foo
JS.console.log (myUrl.toString())
// Prints https://a:b@xn--g6w251d/?abc#foo
let options =
jsOptions<URL.FormatOptions>(fun o ->
o.fragment <- false
o.unicode <- true
o.auth <- false
)
let formatted = url.format(myUrl, options)
JS.console.log formatted
// Prints: https://測試/?abc |
Great! I'm going to see how to merge this. |
Ok found why it would not work! working: [<Import("*", "url")>]
let URL: Url.URLType = jsNative vs not working:
Thanks @MangelMaxime! |
Ah yes indeed:
while [<Import("*", "url")>]
let URL: Url.URLType = jsNative compiles to var url = require("url"); The first one is accessing a global variable while the second one is loading a module. |
Yes should have better read the doc:
|
No description provided.
The text was updated successfully, but these errors were encountered: