mlscript icon indicating copy to clipboard operation
mlscript copied to clipboard

TypeScript Libraries Support

Open NeilKleistGao opened this issue 3 years ago • 18 comments

Implementing ts2mls to allow using TypeScript libraries in MLscript.

Candidate TypeScript Libraries:

  • https://github.com/gcanti/elm-ts
  • https://github.com/gcanti/fp-ts/blob/master/src/Option.ts
  • https://github.com/ionic-team/ionic-framework
  • https://github.com/AykutSarac/jsoncrack.com
  • https://www.npmjs.com/package/@types/lodash

NeilKleistGao avatar Sep 02 '22 06:09 NeilKleistGao

TODO:

  • [x] Generate MLscript declarations in new syntax for classes
  • [x] Generate correct namespace structure by extending namespaces in NewParser.scala

NeilKleistGao avatar Sep 02 '22 06:09 NeilKleistGao

Is it from .ts to .mls, or .d.ts to .mls?

chengluyu avatar Sep 08 '22 09:09 chengluyu

I think it should work with both. Right?

LPTK avatar Sep 08 '22 09:09 LPTK

I think so. I can add some .d.ts tests later.

NeilKleistGao avatar Sep 14 '22 03:09 NeilKleistGao

  • [x] Generate type alias declaration

NeilKleistGao avatar Oct 03 '22 03:10 NeilKleistGao

All interfaces are from TypeScript types.ts

NeilKleistGao avatar Oct 05 '22 01:10 NeilKleistGao

  • [ ] Add private/protected
class A {
    private a: number
    protected b: string
}

NeilKleistGao avatar Oct 11 '22 09:10 NeilKleistGao

  • [ ] deal with export in ts

Example:

export namespace N1 {
    interface IF {
        foo()
    }

    class Base {
        a: number = 10
    }

    export class MyClass extends Base implements IF {
        foo() {}
    }
}

In this case, Base will not be exported so users can't access to it. However, we still need to consider that MyClass extends the Base so we need to add a: number into MyClass

NeilKleistGao avatar Oct 11 '22 10:10 NeilKleistGao

  • [ ] deal with export in ts

Example:

export namespace N1 {
    interface IF {
        foo()
    }

    class Base {
        a: number = 10
    }

    export class MyClass extends Base implements IF {
        foo() {}
    }
}

In this case, Base will not be exported so users can't access to it. However, we still need to consider that MyClass extends the Base so we need to add a: number into MyClass

Also we can create an instance by calling the exported function, but we can't use new:

export namespace N1 {
    class Foo {
        a: number = 10
    }

    export function get(): Foo {
        return new Foo();
    }
}

let x = N1.get()
console.log(x.a)

// error!
// let y = new N1.Foo() 

NeilKleistGao avatar Oct 11 '22 10:10 NeilKleistGao

  • [x] Fix such situation:
const none: Option<never> = { _tag: 'None' }
const some = <A>(a: A): Option<A> => ({ _tag: 'Some', value: a })

NeilKleistGao avatar Oct 11 '22 10:10 NeilKleistGao

Interesting. What's the return type of N1.get() when viewed from the outside of this module/file? If it's something like N1.Foo, then that means we should still export the class, but simply make its constructor private.

LPTK avatar Oct 11 '22 10:10 LPTK

Interesting. What's the return type of N1.get() when viewed from the outside of this module/file? If it's something like N1.Foo, then that means we should still export the class, but simply make its constructor private.

The type I got is:

symbol: <ref *1> SymbolObject {
      flags: 32,
      escapedName: 'Foo',
      declarations: [Array],
      exports: [Map],
      members: [Map],
      valueDeclaration: [NodeObject],
      parent: undefined,
      isReferenced: 788968,
      id: 14
   },

In the members, we can also get private/protected members. So I think we do need a private constructor. 🤔

NeilKleistGao avatar Oct 11 '22 11:10 NeilKleistGao

I also find something like this in https://github.com/gcanti/fp-ts/blob/master/src/Option.ts.

export const URI = 'Option'

I think we'd better convert all stuffs rather than merely functions or interfaces.

NeilKleistGao avatar Oct 14 '22 03:10 NeilKleistGao

Huh, well yeah of course we should convert these too...

LPTK avatar Oct 14 '22 05:10 LPTK

(Note that the URI machinery is for higher kinded types and is used in conditional types, which we don't yet support.)

LPTK avatar Oct 14 '22 05:10 LPTK

  • [ ] Add readonly support(mut in MLScript)

NeilKleistGao avatar Oct 17 '22 03:10 NeilKleistGao

Are you planning to support mapped types, conditional types, etc.?

kevinbarabash avatar Apr 25 '23 01:04 kevinbarabash

@kevinbarabash Yes, the plan is to eventually support arbitrary computations in types (in a way that cleanly generalizes TypeScript's various ad-hoc type computation syntaxes). However, there is a long road before we get there, as for the moment we are busy working out the basic components of the language and type system.

LPTK avatar Apr 25 '23 02:04 LPTK