Fable: ts2fable fails with ' TypeError: Cannot read property 'kind' of undefined'

Created on 9 Nov 2016  路  9Comments  路  Source: fable-compiler/Fable

Description

ts2fable fails with ' TypeError: Cannot read property 'kind' of undefined'

Repro steps

I'd like to get fable to work with Unreal.js, a Javascript plugin for Unreal Engine 4. The API to UE4 is supplied as d.ts, so I hoped to import it. The d.ts files can be found at https://github.com/ncsoft/Unreal.js/tree/master/Examples/Content/Scripts/typings

The failure below was by running
ts2fable _part_0_ue.d.ts

Actual behavior

< TypeError: Cannot read property 'kind' of undefined
<     at getVariables (C:\Users\j\AppData\Roaming\npm\node_modules\ts2fable\ts2fable.js:591:37)
<     at C:\Users\j\AppData\Roaming\npm\node_modules\ts2fable\ts2fable.js:776:36
<     at visitEachNode (C:\Users\j\AppData\Roaming\npm\node_modules\ts2fable\node_modules\typescript\lib\typescript.js:7255:30)
<     at Object.forEachChild (C:\Users\j\AppData\Roaming\npm\node_modules\ts2fable\node_modules\typescript\lib\typescript.js:7412:24)
<     at visitFile (C:\Users\j\AppData\Roaming\npm\node_modules\ts2fable\ts2fable.js:773:8)
<     at Object.<anonymous> (C:\Users\j\AppData\Roaming\npm\node_modules\ts2fable\ts2fable.js:827:20)
<     at Module._compile (module.js:413:34)
<     at Object.Module._extensions..js (module.js:422:10)
<     at Module.load (module.js:357:32)
<     at Function.Module._load (module.js:314:12)

Known workarounds

None

Related information

ts2fable Version 1.22

bug ts2fable

All 9 comments

Sorry I haven't replied to this before. With the new features added to Typescript it's getting more and more difficult to parse the declarations and keep them in sync so I'm looking for alternative ways to make the bindings at the moment. Suggestions are welcome!

This might be a dumb question but is there no way to create a type provider, similar to the powershell type provider?

This is indeed possible and I was also considering it, but it's not without challenge. It'd be nice if the type provider could communicate with the typescript server so it could infer type info also from .js files (not only .d.ts declarations), but this would probably require considerable development effort.

Some possible limitations of the type provider vs the parser:

  • Erased type providers cannot produce generic types. I'm not sure about generative type providers, but these could complicate things even more.
  • If the parser makes an error, any developer with F# knowledge can correct the output. However, to fix errors in the type provider you need to update the type provider itself.

It could be possible to use pre-existing tools to infer a d.ts from an existing JS file, then use the existing d.ts tooling to handle the loose typings produced.
See https://github.com/Microsoft/dts-gen

Why doesn't ts2fable just use the TS compiler itself to parse the file?

Oh, wait a minute, it actually does.
Never mind then. :-)

@jcoder58 in this case ts2fable crashes on variable EOrientPositionSelector (line 183):

declare var EOrientPositionSelector = { Orientation:'Orientation',Position:'Position',OrientationAndPosition:'OrientationAndPosition', };

This declaration is actually illegal in a .d.ts file: it is a variable initialization in a typing declaration. This is not allowed. (just think about it: why would you include initialization value for a variable?)
If you open this .d.ts file in an IDE with TS support (e.g. VS Code), you'll see an error saying: "_Initializers are not allowed in ambient contexts._"

From the initialization value, I could speculate that the true intent of this declaration was to indicate the _type_ of the variable to be { Orientation:'Orientation', Position:'Position',OrientationAndPosition:'OrientationAndPosition' } (though I can't think of a use for such type). If this is the case, you should change the equality sign to a colon:

declare var EOrientPositionSelector: { Orientation:'Orientation',Position:'Position',OrientationAndPosition:'OrientationAndPosition' };

This way, both TypeScript and ts2fable will be happy: TypeScript won't produce an error message, and ts2fable will produce F# code like this:

type [<AllowNullLiteral>] EOrientPositionSelectorType =
    abstract Orientation: obj with get, set
    abstract Position: obj with get, set
    abstract OrientationAndPosition: obj with get, set

type [<Erase>]Globals =
    [<Global>] static member EOrientPositionSelector with get(): EOrientPositionSelectorType = jsNative and set(v: EOrientPositionSelectorType): unit = jsNative

P.S. This is not the only such variable initializer in that file. I would guess that this file was originally written for a very old version of TypeScript and never updated.

To the best of my (limited) understanding, declare var (or similar variations such as let or const) are not only allowed but necessary in some cases to correctly export values. There are newer and better ways, such as export as namespace, but the old way still needs to be supported, as many declaration files used that when it was the only way.

Continued in ts2fable repo

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexfoxgill picture alexfoxgill  路  39Comments

et1975 picture et1975  路  25Comments

SCullman picture SCullman  路  49Comments

alfonsogarciacaro picture alfonsogarciacaro  路  35Comments

matthid picture matthid  路  29Comments