Compiling TSX to JS with Babel not correct - javascript

I'm trying to have babel compile a folder of react tsx files into browser-readable js files in one step. Eveything seems fine, except the compiled JS output still carries the import lines from the tsx files.
I think this is a configuration problem. Here are the key files:
.babelrc
{
"presets": [
[
"#babel/preset-react",
{
"flow": false,
"typescript": true
}
],
[
"#babel/preset-typescript",
{
"isTSX": true,
"allExtensions": true
}
]
],
"plugins": ["#babel/plugin-syntax-class-properties", "react-auto-binding"]
}
tsconfig.json
{
"compilerOptions": {
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"allowJs": true, /* Allow javascript files to be compiled. */
"outDir": "build", /* Redirect output structure to the directory. */
"rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"jsx": "react",
"noEmit": true,
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
/* Additional Checks */
/* Module Resolution Options */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
/* Advanced Options */
"resolveJsonModule": true /* Include modules imported with '.json' extension */
}
}
The file I'm trying to convert (test.tsx):
import * as React from "react";
import ReactDOM from "react-dom";
const e = React.createElement;
class LikeButton extends React.Component {
constructor(props: any) {
super(props);
this.state = { number: 1 };
}
render() {
return (
<div>
<h1>TESTING</h1>
</div>
);
}
testingTS(something: number) {}
}
const domContainer = document.querySelector("#like_button_container");
ReactDOM.render(<LikeButton />, domContainer);
The babel command
npx babel src --out-dir public/scripts --extensions ".tsx"
The file it output (test.js):
import * as React from "react"; <-- this should not be here ---
import ReactDOM from "react-dom"; <-- this should not be here ---
const e = React.createElement;
class LikeButton extends React.Component {
constructor(props) {
super(props);
this.state = {
number: 1
};
}
render() {
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", null, "TESTING"));
}
testingTS(something) {}
}
const domContainer = document.querySelector("#like_button_container");
ReactDOM.render( /*#__PURE__*/React.createElement(LikeButton, null), domContainer);

The problem is that you haven't set the correct output format, add #babel/preset-env to tell babel what format it should use

Related

Module not found: Error: Can't resolve './App' from React 18 w/TypeScript

Getting this error when trying to upgrade to react 18.
I wonder if it has to do with my file types? I'm using typescript so I assume both the app and index have to end with a .tsx?
Teh app and index file are both within the same folder (src)
ERROR in ./src/index.tsx 12:0-24
Module not found: Error: Can't resolve './App' in 'C:\Users\CleverlyDone\Documents\GitHub\myProjectName\src'
My files are:
index.tsx
/** Vendor */
import React from "react";
/** Shared CSS */
import "./dist/css/index.css";
/** Entry Point */
import App from "./App";
/** Analytics */
// import reportWebVitals from "./reportWebVitals";
import { createRoot } from "react-dom/client";
const container = document.getElementById("app");
const root = createRoot(container!);
root.render(<App />);
App.tsx
/** Vendor **/
import React from "react";
/** CSS */
import "./dist/css/app.css";
export default function App() {
return (
<div>Placeholder</div>
);
}
Try adding this to your tsconfig.json
{
"compilerOptions": {
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"jsx": "react-jsx"
},
"include": [
"src",
]
}
Probably problem is in your webpack because you are using Typescript. In your webpack try adding ts and tsx
module.exports = {
//Rest of your code
resolve: {
extensions: ['.ts', '.tsx'],
},
};

Unable to import type from npm library

For a while now I have been using vuex-router-sync in my vue projects to keep my vuex store in sync with my routes.
For my newest project I now use Typescript for the first time.
In that context I am trying to import the State type interface from the library (which is exported according to the source code) in the following way:
import { Module } from "vuex";
import { State } from "vuex-router-sync";
interface RootState {
route: State;
}
const initialState = {};
export const processDetails: Module<any, any> = {
namespaced: true,
state: initialState,
getters: {
processId(_, _2, rootState: RootState): string {
return rootState.route.params.processId;
},
},
};
Expectation:
Above code should typecheck without error.
Actual Behaviour:
Typescript throws the following exception:
Module '"../../node_modules/vuex-router-sync/types"' has no exported member 'State'.
When I look into the file mentioned in the error it infact only contains the type declaration SyncOption which I find confusing since it seems to be exported in the same way as State in the module source code linked above.
Therefore I was wondering why State does not show up in the types file generated and if I can still import this interface somehow.
Contents of node_modules/vuex-router-sync/types/index.d.ts:
import { Store } from 'vuex';
import VueRouter from 'vue-router';
interface SyncOptions {
moduleName: string;
}
export declare function sync(
store: Store<any>,
router: VueRouter,
options?: SyncOptions
): Function;
My tsconfig.json file:
{
"compilerOptions": {
"noImplicitAny": false,
"target": "es5",
"module": "es2020",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"skipLibCheck": true,
"strictFunctionTypes": false,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"resolveJsonModule": true,
"baseUrl": ".",
"types": ["webpack-env", "jest"],
"paths": {
"#/*": ["src/*"]
},
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": ["node_modules"]
}

React,Storybook - TS2307: Cannot find module 'Button' or its corresponding type declarations CAN SB RESOLVE?

I have pure React project (with one Button component) created by "create-reat-app" and I use absolute paths that works with importing Button component to App.js. I've added Storybook and got error while: import { Button, ButtonProps } from 'Button';
The absolute path 'Button' throws an error TS2307 as in title of this post
Project structure:
- App.js
- tsconfig.json
--src
--Button
---Button.js
I tried to add tsconfig with no result:
"compilerOptions": {
// remove error Cannot use JSX unless '--jsx' flag is provided
"jsx": "react",
"esModuleInterop": true,
"moduleResolution": "node",
"strictNullChecks": true,
"rootDir": "src",
"baseUrl": "./",
"paths": {
"src/*": [
"./src/*"
]
}
},
"include": [
"./src",
"./src/**/*.ts",
"./src/**/*.tsx"
]
}```
Change
import { Button, ButtonProps } from 'Button';
to
import { Button, ButtonProps } from './Button';

React props are not inherited in Custom Next.js App component

I created custom next.js App component as a class(with intention to override componentDidMount function with initializing Google analytics).
class MyApp extends App {
async componentDidMount(): Promise<void> {
await initializeAnalytics();
}
render() {
const {Component, pageProps} = this.props;
return (
<Container>
<Component {...pageProps} />
</Container>
);
}
};
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": ["es5", "es2015.promise", "dom"],
"noImplicitAny": true,
"noImplicitReturns": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true,
"jsx": "react",
"baseUrl": ".",
"skipLibCheck": true,
"paths": {
"#myapp/*": ["./node_modules"]
}
}
}
The problem I'm facing is
error TS2339: Property 'props' does not exist on type MyApp.
props field should be inherited from App component that is defined as:
export default class App<P = {}, CP = {}, S = {}> extends React.Component<P & AppProps<CP>,
S> {
static origGetInitialProps: typeof appGetInitialProps;
static getInitialProps: typeof appGetInitialProps;
componentDidCatch(error: Error, _errorInfo: ErrorInfo): void;
render(): JSX.Element;
}
Why does compiler complain about missing props field on MyApp component? Shouldn't it be inherited from App component that extends React.Component?
Used versions:
Typescript 4
Next.js 10.0.0
React 17.0.0
#types/react 17.0.0
You'll need to add "esModuleInterop": true under compilerOptions in your tsconfig.json file.
I'd also suggest you use "jsx": "preserve" to avoid other React-related issues.
for you to use this.props, the props should be a method in the myApp class. therefore this.props doesnt exist as signaled by the compiler

Typescript alias import with auto-complete

===== 2021/03/17 Update =====
If anyone still have the same issue. You can try this:
webpack.config.js
module.exports = {
...
resolve: {
alias: {
components: path.resolve(process.cwd(), './src/components'),
},
},
};
tsconfig.json
{
...
"baseUrl": ".",
"path": {
"components/*": ["./src/components/*"]
}
}
===== Origin Post =====
I have a Alert React component below:
import React from 'react';
interface Props {
message: string;
};
const Alert = (props: Props) => {
return (
<div>{props.message}</div>
);
};
export default Alert;
I use the alias import instead of relative import:
// alias import
import Alert from 'components/Alert';
// relative import
// import Alert from '../../components/Alert';
const App = () => {
return (
<div>
<Alert message="I want to know the interface of Alert" />
</div>
);
};
export default App;
If I type "<Alert me" in relative import, VSCode will show the auto-complete options.
However, when I use the alias import, VSCode won't show the auto-complete.
Is there any possible way to let the VSCode knows the 'components/Alert' is '../../components/Alert', and show me the auto-complete that I can understand the interface of Alert's props?
Here is how I setting the alias, I had been tried both webpack config and tsconfig:
webpack.config.js
...
resolve: {
modules: ['node_modules', 'src'],
extensions: ['.ts', '.tsx', '.js', '.jsx'],
mainFields: ['browser', 'jsnext:main', 'main'],
alias: {
'components/*': path.resolve(process.cwd(), 'src/components/*'),
'containers/*': path.resolve(process.cwd(), 'src/containers/*'),
'images/*': path.resolve(process.cwd(), 'src/images/*'),
'hooks/*': path.resolve(process.cwd(), 'src/hooks/*'),
},
}
tsconfig.json
"compilerOptions": {
...
"baseUrl": "src",
"paths": {
"components": ["components"],
"containers": ["containers"],
"images": ["images"],
"hooks": ["hooks"]
}
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
folder structure:
- src
- components
- Alert
- index.tsx
- containers
- App
- index.tsx
You will have to set the baseUrl option as relative to the paths you are aliasing, so if you have alias path set to ./src/components then the baseUrl of that path is ./.
Here is an example:
"baseUrl": "./",
"paths": {
"#components/*": [
"./src/components/*"
],
or
"baseUrl": "./src",
"paths": {
"#components/*": [
"components/*"
],

Categories

Resources