Skip to content

Conversation

shayanhabibi
Copy link
Contributor

@shayanhabibi shayanhabibi commented Jun 21, 2025

op_Implicit for Erased Unions

Animation3

The suggested change is to provide inlined implicit casting into the erased union.

This would allow method/other calls to accept arguments of the type implicitly in situations where the inferred type is concrete. It will provide an error with generic type parameters and still error unless !^ explicitly cast which is fine. See above.

This would not concretely change anything fundamental about the usage or behaviour of these erased unions in implementation. The advantage here is that the erased union would provide a warning (from the implicit cast) rather than an error, which better
suits the use case of the discriminated union as an interface for F# to dynamic languages when interop-ing.

In this situation, workflow would ideally not be broken when providing an input to bindings that accept multiple types. Especially since the erased operator is defined in the JsInterop module.
I would argue appropriate highlighting of a potential issue that can be adjusted afterwards and made explicit instead of outright being invalid would align with the majority use case of these erased unions.

I've had this implemented in my own libraries for a while as I find it to be a great DX improvement without cost

@MangelMaxime
Copy link
Member

This change reminded me of an experimentation I did for Glutinum: glutinum-org/cli#80

Looking at my comments it seems like one potential issue/limitation is with anonymous record. However, because the proposed changes are for "generics" types and not direct binding like in Glutinum I don't think this limitation apply as much

@shayanhabibi
Copy link
Contributor Author

This change reminded me of an experimentation I did for Glutinum: glutinum-org/cli#80

Looking at my comments it seems like one potential issue/limitation is with anonymous record. However, because the proposed changes are for "generics" types and not direct binding like in Glutinum I don't think this limitation apply as much

A good example of how it's so easy to tunnel vision and miss obvious bugs/issues, I would have never thought there were issues with anonymous records and hit a real head scratcher if something like that happened. Thank you for the info, I'll have to try remember to put this in a PR for the docs at some point when Fable 5 is coming getting released

@shayanhabibi
Copy link
Contributor Author

I'm going to quickly take this chance to add this to the xml docs

@MangelMaxime
Copy link
Member

I would have never thought there were issues with anonymous records and hit a real head scratcher if something like that happened.

Yes, it is difficult to remember that anonymous record have this limitation because I think they are the only F# type to have it.

I probably discovered it because Glutinum "stupidly" generate code and its how I am mapping literal types in certain scenario.

@shayanhabibi
Copy link
Contributor Author

shayanhabibi commented Jun 21, 2025

Full type docs are not shown with code completion/intellisense as demonstrated in second image. I like this, what do you think?

image

image

Thoughts on this type of doc usage? According to MSDN it's standard, but I only have real experience with Rider.

/// <summary>
/// Erased union type to represent one of two possible value types mainly intended for typing the signature of imported
/// JS functions.
/// </summary>
/// <remarks>
/// Pattern matching is possible, but should consider the implications of the Erased union and JS type testing (see the
/// docs for details).<br/>
/// Member concrete types will be implicitly cast into the union, and will provide a warning to this effect. Usage of
/// the explicit cast operator <c>!^</c> available in <c>Fable.Core.JsInterop</c> will remove this warning.
/// <a href="https://github.com/fable-compiler/Fable/pull/4143">Collection types, can provide an error</a> that will
/// only be resolved with the explicit operator. <a href="https://github.com/glutinum-org/cli/issues/80">Anonymous
/// records have other considerations that may be relevant if you are encountering issues.</a>
/// <code>
/// let test(arg: U3&lt;string, int, float[]>) =
///     match arg with
///     | U3.Case1 x -> printfn "A string %s" x
///     | U3.Case2 x -> printfn "An int %i" x
///     | U3.Case3 xs -> Array.sum xs |> printfn "An array with sum %f"
/// </code>
/// </remarks>
/// <seealso href="https://fable.io/docs/communicate/js-from-fable.html#erase-attribute"/>

@MangelMaxime
Copy link
Member

Full type docs are not shown with code completion/intellisense as demonstrated in second image.

Seems good to me, as long as we have the full tooltip using hover

Can you please use <code lang="fsharp"> for the code block, this is because Ionide use the lang attribute to add syntax highlighting 😇

I also discovered that <code> inside of <remarks> is broken in Ionide, so I will have a look to fix it.

I would also place <br/> alone on its line, but that's a personal preference.

@shayanhabibi
Copy link
Contributor Author

shayanhabibi commented Jun 23, 2025

Can you please use <code lang="fsharp"> for the code block, this is because Ionide use the lang attribute to add syntax highlighting 😇

Tsk. Jealous 😢 .

Do we have a general time frame for Fable 5? I'd like to have a through and through on the codebase to update documentation before its released

@shayanhabibi shayanhabibi marked this pull request as draft June 23, 2025 16:58
@MangelMaxime
Copy link
Member

There is not time frame for Fable 5 but it will happens after this 2 features are done:

  • Complete nullable support I need to adapt my branch to only do check at runtime for JS/TS because that's enough and I don't know how to deal with TypeScript compiler detection for null check (It expects a specific version of the code to be generated)
  • JSX supports is completed

The reason to way for both of these features is because they can introduce change to the AST or big AST manipulation.

I would love also to rework the CLI commands/arguments but this can be done latter in a Fable 6 release.

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

Successfully merging this pull request may close these issues.

2 participants