fable-compiler/ts2fable

keyof is ignored

Booksbaum opened this issue · 1 comments

ts2fable ignores the keyof keyword and instead just continues with its containing type: keyof T -> 'T.
This changes types:

function f(k: keyof number): keyof SomeType
abstract f: k: float -> SomeType

-> keyof number changes to just number (-> float), keyof SomeType to just SomeType

TypeScript docs:

An indexed type query keyof T yields the type of permitted property names for T. A keyof T type is considered a subtype of string.

There's no direct match in F#. So string would be correct for every keyof XXX usage. But string doesn't contain any information that a property name of some type is required.

I propose to introduce a new type:

[<Erase>]
type KeyOf<'T> = Key of string

The example above would result in:

abstract f: k: KeyOf<float> -> KeyOf<SomeType>

KeyOf clearly marks something as keyof and requires special handling by the user. Considering there's no direct check for a valid key, that's probably the best we can do.



Special case: keyof as generic type parameter constraint:

function f<T, K extends keyof T>(t: T, k: K): [T, K]

Here type parameter K must be removed and all occurrences of K replaced with keyof T

abstract f: t: 'T * k: KeyOf<'T> -> 'T * KeyOf<'T>

Sounds like a good compromise. It could be possible to generate a StringEnum if we know the possible values of keyof T but it may be complicated: doesn't work with generics, potential duplication...