2

I'm using TypeScript 2 and TSX with the preserve (not React) setting and with "noImplicitAny" enabled:

"noImplicitAny": true,
"jsx": "preserve"

The problem is, I keep getting this error when trying to build a simple TSX file:

error TS2602: JSX element implicitly has type 'any' because the global type 'JSX.Element' does not exist.

Here's an example of my TSX file:

'use strict';

import m from './m';

export default {
  view() {
    return (
      <h1>Hello Mithril!</h1>
    );
  }
};

I'm trying to get TSX working with a non-React stack (Mithril). Thanks in advance!

youen
  • 1,952
  • 1
  • 23
  • 32
Christopher Davies
  • 4,461
  • 2
  • 34
  • 33

3 Answers3

2

Answer to original question: (how to solve the TS2602 error)

This is quite simple, as explained here:

As the errors say: "because the global type 'JSX.Element' does not exist"

you can define those types:

declare namespace JSX {
  interface Element { }
  interface IntrinsicElements { div: any; }
}

I recommend getting the react-jsx.d.ts file from DefinitelyTyped

You can use this file as a source for more complete typings (you'll need definitions for every sub-element in IntrinsicElements, i.e. div, p, a, etc.)

Getting farther with TSX and Mithril:

Once you've solved the typing issues, you'll find that you're not quite there. If you use the "jsx": "preserve" setting, the HTML code will be written directly in the generated js file, without any translation. This of course can't be loaded by a web browser (because it's a javascript file, not an html file).

I think there are two ways to make it work:

First solution that comes to mind is to use "jsx":"react" and write a small wrapper that will forward the calls to mithril, like this:

class React {
  public static createElement(selector: string, attributes: object, ...children: Mithril.Child[]): Mithril.Child {
    return m(selector, attributes, children);
  }
}

This is the solution I'm currently using because it doesn't involve additional tools.

The other solution is to keep "jsx":"preserve" and use Babel, as described in mithril documentation, to translate the jsx file (which is generated by typescript from the tsx file) to a valid js file.

In the end, I've managed to make it work, but I found the process quite messy, with typescript/npm module system getting in the way to have JSX types extend Mithril types (so that your functions can return mithril-compatible types), etc. I had to modify the mithril typings (and drop npm @types/mithril), and add a few modules of my own.

I'm interested to know if someone solved this problem in an elegant and simple way!

Community
  • 1
  • 1
youen
  • 1,952
  • 1
  • 23
  • 32
2

Due to the lack of reputation it won't let me comment on youen's answer above so I'll include this in an answer of my own.

First of all, you can include this gist at the top of your project and name it something like mithril-jsx.d.ts so that typescript will see it as a type definition and won't compile it. The linked gist simply declares JSX.element as m.Vnode<any, any> and lists every HTML element under JSX.IntrinsicElements as any. Not a huge deal but a time saver.

Second, and the reason I'm even posting this: You do not need gulp or any other tool to compile .tsx files to mithril-using .js ones. All you have to do is specify these in your tsconfig.json

{
  "compilerOptions": {
    //...your other stuff here
    "jsx": "react",
    "jsxFactory": "m"
  }
}

More information about the compiler options here: http://www.typescriptlang.org/docs/handbook/compiler-options.html

Nick
  • 106
  • 4
  • Hey nice tip, I did not know about the "jsxFactory" option. I was using `"jsx":"react"` and then made a wrapper to call `m` instead, at run-time. However does it output actual mithril compatible syntax? Because I think react takes a list of parameters for children, while mithril takes a single parameter which is an array? – youen Jul 17 '17 at 08:18
  • Yes `{ "jsxFactory": "m" }` works great, same idea as the [babel plugin](https://mithril.js.org/jsx.html#setup) `["transform-react-jsx", { "pragma": "m" }]`. – piedar Nov 05 '18 at 01:31
0

I am also developing with Mithril(2.0.3) and TypeScript(3.5.3).

TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.

This error message can be resolved by installing @types/react.

npm install --save-dev @types/react

tsconfig.json has the following settings.

{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "m"
  }
}
Tsuru
  • 1
  • 1