Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

Trying to generate React bindings in non-tsx files? #213

Closed
zeh opened this issue Feb 17, 2017 · 10 comments
Closed

Trying to generate React bindings in non-tsx files? #213

zeh opened this issue Feb 17, 2017 · 10 comments

Comments

@zeh
Copy link
Contributor

zeh commented Feb 17, 2017

Apologies if this is not the right place for questions, but I've started porting a site build system I have from Webpack to Fuse-box and ran into a snag. I would appreciate any input.

The project in question uses TypeScript 2.2 + React + Redux + PostCSS. This is my current attempt at a build script:

const fsbx = require("fuse-box");

fsbx.FuseBox.init({
    homeDir: "src/",
    outFile: "./dist2/app.js",
    sourceMap: {
        bundleReference: "app.js.map",
        outFile: "./dist2/app.js.map",
    },
    plugins: [
        fsbx.TypeScriptHelpers(),
    ]
}).devServer(">[ts/main.tsx]");

When I run this, I get this message:

$ node build
16:30:54 : Launching dev server on port 4444
  → Typescript config:  \tsconfig.json
Acorn error: Unexpected token (13:4)
File: D:\<...>\src\ts\data\stores\reducers\search.ts

11      React.createElement("string", null,
12          "):ISearch => ",
13      ,
14          " ",
15          React.createElement(model_1.ISearch, null,
16              "Object.assign(",
17              ", state, ",

So it's apparently trying to interpret that file as a React file, and tripping on the comma at line 13. But it's not what the file is; it's just a reducer to a Redux store. This is its full contents:

import { Action, handleActions } from "redux-actions";
import { ISearch } from "./../model";
import {
	CLEAR_SEARCH_TEXT,
	SET_SEARCH_TEXT,
} from "./../actions";

const initialState:ISearch = <ISearch>{
	text: "",
};

export default handleActions<ISearch, any>({
	[SET_SEARCH_TEXT]: (state:ISearch, action:Action<string>):ISearch => {
		return <ISearch>Object.assign({}, state, {
			text: action.payload,
		});
	},
	[CLEAR_SEARCH_TEXT]: (state:ISearch, action:Action<void>):ISearch => {
		return <ISearch>Object.assign({}, state, {
			text: "",
		});
	},
}, initialState);

A wild guess is that it's getting tripped by the < and > in the generics method declaration, but that seems... silly.

Anyone know what I'm doing wrong? The tsx-ish examples I've found are all over the place and they just mention automatic ts/tsx interpretation.

My tsconfig, for reference:

{
	"compilerOptions": {
		"target": "es6",
		"module": "commonjs",
		"strictNullChecks": true,
		"noUnusedParameters": false,
		"noUnusedLocals": true,
		"noImplicitAny": true,
		"noImplicitThis": true,
		"noImplicitReturns": true,
		"sourceMap": true,
		"jsx": "react"
	},
	"include": [
		"node_modules/@types/**/*.d.ts",
		"./src/ts/**/*"
	],
	"exclude": [
		"./dist/**"
	],
	"compileOnSave": false
}

Update: it seems the part that's tripping the compiler is any <...> cast, not the generic method. In the above case, all <ISearch>... casts cause it to fail. Replacing it by the other casting syntax (... as ISearch) makes it work.

After fixing search.ts above, another file was running into the same problem. This was was the faulty code:

if (this.sequences[i] !== null) {
	(<FweenSequence>this.sequences[i]).update();
} else {

Changing it to this fixes the issue:

if (this.sequences[i] !== null) {
	(this.sequences[i] as FweenSequence).update();
} else {

So there we go.

@nchanged
Copy link
Contributor

@zeh hi!
It seems like fusebox does not understand your .ts file.

Acorn error: Unexpected token (13:4)
File: D:\<...>\src\ts\data\stores\reducers\search.ts

You should not be seeing that. This one \src\ts\data\stores\reducers\search.js what it should have transpiled to.

Also, there might be an issue with the latest TypeScript 2.2, I am not sure if it helps dropping the version, but that definitely looks like a bug. Could you try typescript 2.1.6 + cleaning the cache?

Thanks

@zeh
Copy link
Contributor Author

zeh commented Feb 17, 2017

Hey @nchanged, thanks for the response.

Same error on TS 2.1.6 + cleared cache.

I managed to get past that error by removing all <ISearch> casts though, and replacing them with ...as ISearch. So I was wrong, it's not the generic method signature that's the culprit. It's still an error, but at least one that can be circumvented.

@nchanged
Copy link
Contributor

@zeh good one.
Can you confirm that the code that bugged up compiles without problems with just using the typescript compiler? All I am saying, can we blame fusebox?

Thanks.

@zeh
Copy link
Contributor Author

zeh commented Feb 17, 2017

@nchanged It definitely compiles. Castings might be uncommon but it's legal TypeScript and I currently use it within my webpack/tsc build with no problem.

"blaming" might be a strong word as I'm not sure I'm doing something wrong instead, but it's definitely tripping fusebox.

@nchanged
Copy link
Contributor

Can I kindly ask you to take a look at this piece

Do you think it might be somewhat different from the CLI interface? And if you have an idea how to fix it, please share ;-)

@basarat
Copy link
Contributor

basarat commented Feb 17, 2017

@zeh as a fellow user of fusebox, if you can share an example project I will hack hard at it till I get it to work for you 🌹

zeh added a commit to zeh/fuse-box that referenced this issue Feb 17, 2017
When transpiling files as modules, the filename is passed to TypeScript so it can interpret it properly. This is necessary to respect the behavior of the command line, especially when deciding whether files should be interpreted as jsx/tsx files, as per [the transpiler reference](https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#transpiling-a-single-file).

See fuse-box#213.
@zeh
Copy link
Contributor Author

zeh commented Feb 17, 2017

@nchanged Thanks so much for the link. I see now what the issue is.

Because fuse-box is calling typescript.transpileModule for the file without passing its filename, the TypeScript transpiler doesn't know whether to interpret the source as a .ts or a .tsx file. Therefore it follows tsconfig's value: if jsx is set to react, it will always interpret the file as .tsx.

As per the API documentation:

Usually TypeScript compiler uses file extension to determine if file should be parsed as '.tsx' or '.ts'. The same rule is applied during single file transpilation if the file name is provided. If the file name is omitted, then compiler will check if the jsx options is specified. If it is set and is not JsxEmit.None, then source text will be interpreted as '.tsx'.

The <...> casts always fail on tsx files, so avoiding passing the filename can break compliant code.

I've submitted a small PR that attempts to do so, so fuse-box will follow tsc's behavior more closely. I've tested it locally and it compiles my offending file without a glitch.


Now. With that said, <...> casts do seem to create enough problems with TypeScript to the point where it's not recommended usage anymore. It's reported here: #6897. Using ...as X seems to be the recommended way, as it was introduced in response to this problem.

My current webpack/tsc/babel stack was following the command line behavior, and that's why it was working.

TL;DR: <...> should work, and now there's a PR to fix that, but they're not recommended anyway, so anyone running into this issue is probably better changing it to ...as casts.

@basarat Thanks. I was going to do that, but decided to take a look at the source and ended up running into the solution earlier than I expected.

@zeh
Copy link
Contributor Author

zeh commented Feb 17, 2017

Closed; fixed by #216. Thanks @nchanged.

@zeh zeh closed this as completed Feb 17, 2017
@nchanged
Copy link
Contributor

@zeh stunning! thanks a billion!

@basarat
Copy link
Contributor

basarat commented Feb 18, 2017

but they're not recommended anyway

True. I always use as https://basarat.gitbooks.io/typescript/content/docs/types/type-assertion.html 🌹

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants