3

What is a simple way to have TypeScript recognize JSX (especially in VS Code) without having React as a dependency? If we have to use a custom JSX namespace and a custom renderer, then what is the expected shape of the contents of that namespace and the renderer?

As far as I know, JSX is just syntactic sugar that is transformed into function calls (e.g., React.createElement), so there should be a way to specify that a different function should be used for transforming the JSX.

Looking at the release docs for TypeScript 2.8, I see there are sections titled "Per-file JSX factories" and "Locally scoped JSX namespaces", but I don't see these sections in the official current TypeScript docs. Have these features been deprecated?

prmph
  • 7,616
  • 11
  • 37
  • 46
  • Possible duplicate of [can i use jsx without React to inline html in script?](https://stackoverflow.com/questions/30430982/can-i-use-jsx-without-react-to-inline-html-in-script) – Bourbia Brahim Jan 11 '19 at 10:12
  • 1
    @Berr'ita: This is not a duplicate. I specifically indicated out I want to use TypeScript in VSCode (to retain the intellisense features). The other question talks about babel plugins and third-party packages, which I don't want – prmph Jan 11 '19 at 10:43

2 Answers2

4

jsx and jsxFactory compiler options are responsible for that.

TypeScript expects a function defined in jsxFactory to exist in module scope. Usually this requires to import React because jsxFactory defaults to React.createElement.

If the compiler is configured with:

...
"jsx": "react",
"jsxFactory": "h",
...

Then h function should exist. JSX-related types should be defined to make type checks work properly:

declare namespace JSX {
  interface Element {}
  interface ElementClass {
    render(): any;
  }
  interface IntrinsicElements {
    div: any;
    // ...
  }
}

const h = (Comp: any): any => console.log(`creating ${Comp} element`);

<div/>;

class FooComponent {
  render = () => null;
}

<FooComponent/>;
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • Thanks @estus: Does this mean that all components you define have to be added to the _JSX.IntrinsicElements_ structure? Can you provide an example of defining a custom component that will be recognized by this scheme? – prmph Jan 11 '19 at 10:37
  • Not exactly. IntrinsicElements are for HTML and SVG. You can use React's own types as starting point, https://github.com/DefinitelyTyped/DefinitelyTyped/blob/826ce0f1ce1d1887d199986283630d6f63075ad5/types/react/index.d.ts#L2656 – Estus Flask Jan 11 '19 at 10:59
  • Can you actually provide a code snippet of a custom non-react component that is type-checked by TypeScript? It seems that is the best way to get at the problem I am having – prmph Jan 11 '19 at 11:03
  • Ok @estus, what about functional components? I've tried them and they mostly work, but sometimes there are some weird type errors. For example, `const FComp = () =>
    ` gives an error, but `const FComp = () => {return
    }` does not
    – prmph Jan 11 '19 at 11:10
  • Also @estus, evaluating `` by itself gives an error, but `let elt = ` does not – prmph Jan 11 '19 at 11:11
  • Functional components should work out of the box. It shouldn't cause an error. What code did you try? I assume you didn't put a semicolon between lines. A function should return a thing that is valid Reat-like element(JSX.Element, null, etc). Check https://www.typescriptlang.org/docs/handbook/jsx.html for reference. – Estus Flask Jan 11 '19 at 11:33
  • Seems like https://github.com/nicojs/typed-html is a nice way of doing this. – GreeneCreations Jun 04 '20 at 22:45
1

The Typescript compiler has flags that allow you to specify how TSX/JSX is handled.

Specifically, you have to specify "--jsx=React" and "--jsxFactory=someModule.yourJsxFactory", and in your tsx files, you supply your custom factory by importing "someModule", from which "yourJsxFactory" should be exported.

Read more about it at
Typescript (Compiler Options)
and
Typescript (JSX)

  • @Kaldestad: I have read those documents, and I still have specific questions. If you can provide a specific answer to my questions, I would appreciate that – prmph Jan 11 '19 at 10:12
  • @prmph It's a bit weird that you have to specify "--jsx=React" when you specifically want jsx to be handled NOT by React, but that's the way the cookie crumbles – Ola Næss Kaldestad Jan 11 '19 at 10:25
  • @prmph I've added some further specification to my answer now – Ola Næss Kaldestad Jan 11 '19 at 10:30
  • @ Kaldestad: Yes, the _"jsx:"react"_ bit is confusing. Also, there is more to this than the docs explain. For example, what is the expected shape of the _JSX.IntrinsicElements_ types? – prmph Jan 11 '19 at 10:31
  • @prmph Maybe that's a bit unclear in the docs, I agree. I've found @types/react [on github](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts) to be a good guide. In essence, it should provide type information for the "official" html elements. Or not, you can choose to omit it entirely as stated in the docs. – Ola Næss Kaldestad Jan 11 '19 at 10:37
  • @ Kaldestad: Thanks for updating the link; the first version was dead. But I still don't have what I need. How do you get the JSX engine to recognize a custom component that is not part of the intrinsic elements? – prmph Jan 11 '19 at 10:45
  • @prmph I'm not sure what you mean by "recognize a custom component". The factory will either handle, or fail to handle, anything that's thrown at it. The easiest way to figure this stuff out would be to simply try it out. If you are wondering how to create types that concern custom components, again, look to either official TS docs, or to something like @types/react, where this is all implemented and open for anyone to see. – Ola Næss Kaldestad Jan 11 '19 at 11:10
  • @Kaldestad: Please see my thread with estus below, you will understand what I'm getting at – prmph Jan 11 '19 at 11:13
  • @prmph I see it, and you're essentially asking us to debug your code, or give very specific implementation details, which is entirely outside the original question. And again, why not look at react on github, where all this is implemented already? – Ola Næss Kaldestad Jan 11 '19 at 11:19
  • @Kaldestad: No, I am not asking you to debug my code. I am just using a very minimal implementation to demonstrate the ways in which the official docs falls short. What is the use of the docs if what they contain doesn't actually work, or is so vague as to not permit a working implementation? – prmph Jan 11 '19 at 11:24