core icon indicating copy to clipboard operation
core copied to clipboard

Type annotations

Open Jand42 opened this issue 8 years ago • 3 comments

Main challenge of TypeScript annotations is that there is no type inference like F# (constraint solving), only type checking. So if there is an uninitialized variable like var x;, it will have type any unless annotated: var x: number;. Just having typed signature but under-typed implementation leads to many different type check errors. Method signatures are already in place, so there are further tasks for having correctly typed TypeScript output:

  • [ ] 1) Convert WebSharper's runtime.js to TypeScript
  • [x] 2) Add types to translations of module let values
  • [x] 3) Create separate TS interfaces for F# union cases. Full type of the union type MyUnion = X of int | Y of string would be type MyUnion = MyUnion.Class & (MyUnion.X | MyUnion.Y) where MyUnion.X is defined with { $:0; $1:number } (form of unions in WS runtime)
  • [x] 4) Whenever a string/array is converted to an IEnumerable, wrap it in a StringEnumerator/ArrayEnumerator immediately, instead of handling translation of GetEnumerator specially
  • [ ] 5) local variables should not be collected on top of function scope any more, but defined with let/const (#816) so that TS type inference can resolve their types.
  • [ ] 6) Types with Prototype(false) should translate to a TS interface, declaring the types of the properties (values are plain objects).
  • [x] 7) Tuple types are never inferred, only arrays: [1, "hi"] will be taken as an (number | string)[] instead of [number, string]. So type annotations are needed: <[number, string]>[1, "hi"] for creating tuples. Details in #822
  • [x] 8) Allow the Type attribute on generic parameters to specify that only types are allowed that translate or is compatible with a specific TS type. For example, on Seq.average proxy, the result is always a number but it is generic in .NET. If the proxy would define it like let Average<[<Type "number">] 'T> (s: seq<'T>) : 'T, then WebSharper would know that in TS, it can erase the T type parameter and have it translate to number, also throw a compiler error when it is used with a type that is not mapped to number.
  • [x] 9) Transform checks against interfaces to a function that returns a user-defined type guard.
  • [x] 10) Transform delegate types. Details at #824
  • [ ] 11) (optional) Print consts for enum cases, have a type alias for them (just aliasing number)
  • [x] 12) Map types of 2-dimensional arrays

Jand42 avatar Oct 11 '17 16:10 Jand42

On 4):

Original description: Translate the IEnumerable types to an union of IEnumerable<T> | T[] | string (because WS enumeration can handle arrays and strings specially)

To not have a messy type for IEnumerables, it is easier to have them translate directly to the interface type. This needs a runtime change in the handling of enumerating on strings and arrays: instead of a runtime type check at the point of the GetEnumerator call, wrap strings and arrays where they are converted to a sequence into StringEnumerator/ArrayEnumerator helpers that implement GetEnumerator.

Jand42 avatar Oct 11 '17 17:10 Jand42

  1. Needs some more casts for accessing this within members of the union class as a strongly typed union (in TS, a union of cases). Type checks has to be translated against the class type, not the combined union type.

  2. Was solved by extending built-in Array and String to have GetEnumerable. Need to set the prototypes in WebSharper.Main.ts.

Jand42 avatar Oct 12 '17 20:10 Jand42

  1. We can't rely on type inference to resolve the type of every var because WebSharper might need to print uninitialized variables. The type of every local variable will be persisted, so that var/let declarations without assignment can have the type annotation.

  2. Type annotations will not be stored for lambdas but tuple value creation because they are the underlying cause for this error. A tuple will be always translated with type annotations, like <string, number>["hello", 3].

Jand42 avatar Oct 13 '17 12:10 Jand42