Typescript: how can i mix 2 JSX framework in the same project?

Created on 26 Apr 2017  ·  13Comments  ·  Source: microsoft/TypeScript

my client uses React, my server uses homemade JSX factory, React JSX definitions mess up server JSX definitions, is there a way of not making them global so they don't see each other?

a working example of a setup of a project with React + other JSX would be much appreciated

Fixed Needs Proposal Suggestion

Most helpful comment

This remains a huge issue for us. We have a complex set of packages that are assembled in to different top level applications. Each of those packages may need a different JSX namespace. Is there a benefit to having that namespace be global and not per module?

All 13 comments

is there a way of not making them global so they don't see each other

No. JSX type is looked up globally. Similarly the emitter for JSX is global reactNamespace e.g. if instead of using React you are using Th, your config would look like : https://github.com/typehtml/typehtml/blob/2af41218f93e836ced283d373fc10a396f7d1d46/tsconfig.json#L3-L4 :rose:

Adding @staltz for cycleJS https://github.com/cyclejs/cyclejs as he might have ideas :heart:

at the compile time i can separate them by excluding/including only the right files, but what's extremely annoying is that at design time (when i am coding) my experience depends on which file server-jsx.d.ts or client-jsx.d.ts gets loaded to IDE first, so it's either the client code all messed up or the server one

@RyanCavanaugh what is the rationale for JSX to be looked for in a global namespace? i wish i could do it like this:

import * as custom from 'custom/jsx';
import JSX = custom.JSX;
// ...

what is the rationale for JSX to be looked for in a global namespace? i wish i could do it like this:

normally you would not import JSX, it has no runtime impact. you would import react or some other library.

at the compile time i can separate them by excluding/including only the right files, but what's extremely annoying is that at design time (when i am coding) my experience depends on which file server-jsx.d.ts or client-jsx.d.ts gets loaded to IDE first, so it's either the client code all messed up or the server one

Why is it that you do not have two tsconfig.json files?

Why is it that you do not have two tsconfig.json files?

I have 2 config files, but it only helps when I compile, not when I am developing. There is no problem with compiling the client and the server code separately. There is a problem when you develop the code for the entire application with interconnected parts.

The client and the server come very close as you work on a feature, for example: the client needs some data from the server being passed over a piece of HTML/JS markup. So you need to make sure the client is expecting it at the same place where the server is going to provide it. So ideally you want to check through a full-text-search within the same set of files that there are 2 places: one at the supplier side (server) and one at the receiver side (client) that match. If I separate this into 2 differnt projects (one for the client and one for the server) it's twice as much work:

  1. get a search ready
  2. open the client
  3. do the search
  4. make sure you found it
  5. open the server
  6. do the search
  7. make sure you found it

And what I want instead is:

  1. do the search
  2. make sure you found it in client
  3. make sure you found it in server

Is my point clear?

Again, in order to be able to oversee my both client and server within the same set of files, all I need it that 2 different JSX played nice with each other.

I feel like this is more general. It would be very useful to be able to specify that, at runtime, a non-relative import maps to different dependencies depending on the location of the importing module. If that were possible then this might well be resolvable via declare global.

This is a pain point for me as well. I need two separate projects with two tsconfig.json files and I can't even require() files between them even though they are one program / process for me.

Babel let me override the "jsxFactory" in a .babelrc for a subdirectory (or even a single file with a comment) without it being a separate project (though, babel doesn't really have a 'project'...)

What you can do is importing 'fake' react object that have createElement method.

eg
fileWithCutomJSX.ts

import React from './fakeReact.ts'

const jsxFromCustomFactory = (<div />);

fakeReact.ts

const fakeReact = {
  createElement: (...args) => {...args};
}
export default fakeReact;

As jsx factory in tsconfig.json is React.createElement - it'd use your 'fake' one in scope of single file that has imported it.

It'll work but I think there should be some 'core' solution for that in TS.

Also it'll propably cause some ts complains about wrong types as TS JSX is quite strongly tied with React JSX sadly.

I think JSX be treated in more general way where JSX is treated as data structure, not some specific use case od that like DOM element.

I also it would unlock many potential great useages of JSX as JSX is great for defining complex structures of any data.

just faking the factoring isn't enough

problem is that JSX namespace is global (ambient) so its definition is always the same to all files in the project, whereas what's needed is that different files have different JSX definitions within the same project

@aleksey-bykov this seems related as well https://github.com/Microsoft/TypeScript/issues/11917

This remains a huge issue for us. We have a complex set of packages that are assembled in to different top level applications. Each of those packages may need a different JSX namespace. Is there a benefit to having that namespace be global and not per module?

Random update: We provided a fix for this a few releases ago (TS 2.8). You can specify a non-global JSX namespace within the same namespace as the factory function, and a per-file factory function using an @jsx pragma comment, similar to babel.

Was this page helpful?
0 / 5 - 0 ratings