glutinum-org / cli

https://glutinum.net/
59 stars 6 forks source link

Exemple of custom erased types #80

Open MangelMaxime opened 7 months ago

MangelMaxime commented 7 months ago

TypeScript documentation:

export type CategoryPropType =
  | string[]
  | { x: string[] }
  | { y: string[] }
  | {
      x: string[];
      y: string[];
    };

translates into


[<Erase>]
type CategoryPropType =
    | Case1 of ResizeArray<string>
    | Case2 of {| x: ResizeArray<string> |}
    | Case3 of {| y: ResizeArray<string> |}
    | Case4 of {| x: ResizeArray<string>; y: ResizeArray<string> |}

    static member op_ErasedCast(x: ResizeArray<string>) = Case1 x
    static member op_ErasedCast(x: {| x: ResizeArray<string> |}) = Case2 x
    static member op_ErasedCast(x: {| y: ResizeArray<string> |}) = Case3 x
    static member op_ErasedCast(x: {| x: ResizeArray<string>; y: ResizeArray<string> |}) = Case4 x

    static member inline op_Implicit(x: ResizeArray<string>) = Case1 x
    static member inline op_Implicit(x: {| x: ResizeArray<string> |}) = Case2 x
    static member inline op_Implicit(x: {| y: ResizeArray<string> |}) = Case3 x
    static member inline op_Implicit(x: {| x: ResizeArray<string>; y: ResizeArray<string> |}) = Case4 x

[!NOTE] Should generate the literal types as ParamObject

Example of npm package using this features:

MangelMaxime commented 2 months ago

I think I have been confused on how op_Implicit works it actual does the opposition I think:

[<StringEnum>]
type MyType =
    | MyString
    with
        static member inline op_Implicit (x: MyType ) : string = !!x // auto-generate this line

type Test3 =

    static member test(v : string) =
        printfn "%A" v

let x = Test3.test (MyType.MyString)
MangelMaxime commented 2 months ago

Well perhaps it can supports both ways in fact 😅: https://robkuz.github.io/Explicit-vs-Implicit/

But there is still a problem, anonymous record declared from different assemblies are not "compatible" with one another...

MangelMaxime commented 2 months ago

Working code:

[<RequireQualifiedAccess>]
[<Erase>]
type CategoryPropType =
    | Case1 of ResizeArray<string>
    | Case2 of CategoryPropType.U4.Case2

    static member op_Implicit(categories: ResizeArray<string>) = Case1(categories)
    static member op_Implicit(categories: CategoryPropType.U4.Case2) = Case2(categories)
module CategoryPropType =

    module U4 =

        [<Global>]
        [<AllowNullLiteral>]
        type Case2 [<ParamObject; Emit("$0")>] (x: ResizeArray<string>) =

            member val x: ResizeArray<string> = nativeOnly with get, set

Property definition:

module Utils =

    let inline (!>) (x: ^a) : ^b =
        ((^a or ^b): (static member op_Implicit: ^a -> ^b) x)

[<Erase>]
[<Interface>]
type VictoryDatableProps<'IDelayedTypeProperty> =

    static member inline categories(categories: CategoryPropType) =
        Interop.mkDelayedTypeProperty<'IDelayedTypeProperty> "categories" categories