I'm attempting to use TypeScript's paths option in my tsconfig.json file. I've used paths before in my other web applications using React. Yet, for some reason, Native refuses to work with it.
This is my tsconfig.json file:
// Added by default by React Native
"extends": "#tsconfig/react-native/tsconfig.json",
// My options
"compilerOptions": {
"baseUrl": "./App",
"paths": {
"#Assets/*": ["Assets/*"],
"#Image/*": ["Assets/Images/*"],
},
"skipLibCheck": true,
}
This is my folder structure:
project
|__App
| |__Main.tsx
| |__Assets
| |__Images
| |__Test.png
|__tsconfig.json
And inside my Main.tsx file, this is how I'm attempting to use it:
const test = require("#Image/Test.png");
But, this results in the error:
Unable to resolve module #Image/Test.png from project/App/Main.tsx: #Image/Test.png could not be found within the project or in these directories.
I've attempted all of the answers within this thread with no different outcome.
I know that the file does exist because it works perfectly fine when I change the require path to the absolute path.
Related
I have a Typescript library that is being consumed from a React app. I wanted to import the TS library contents with sub-paths like
import {base} from "my-lib"
import {foo} from "my-lib/path1"
import {bar} from "my-lib/path2"
I came across the Github issue which states that this is not yet supported (exports in package.json) by Typescript. I'm using Typescript 4.3.
There is a workaround posted in the same thread - Github repo typescript-subpath-exports-workaround. It uses exports and typeVersions
{
"main": "dist/index.js",
"types": "dist-types/index.d.ts",
"exports": {
".": "./dist/index.js",
"./exported": "./dist/exported.js"
},
"typesVersions": {
"*": {
"exported": ["dist-types/exported"]
}
}
}
I created a new react app (via npx create-react-app command) and tried importing hello from typescript-subpath-exports-workaround and it worked fine. But couldn't import `typescript-subpath-exports-workaround/exported
import {hello} from "typescript-subpath-exports-workaround" //works fine
import {foo} from "typescript-subpath-exports-workaround/exported" //gives "Module not found" error
Full error is below:
./src/App.js
Module not found: Can't resolve 'typescript-subpath-exports-workaround/exported' in '/Users/...../my-react-app/src'
Codesandbox code - https://codesandbox.io/s/create-react-app-forked-5yxd8
UPDATE: The sub-path used in import and the folder structure are different. In the above example, there won't be a folder named path1 or path2.
Look at the Next.JS React Framework. You can see that they use exactly the same approach as you have described. You can create a simple typescript application with their CLI tool like this:
npx create-next-app#latest --typescript
Then pay attention on imports used for instance in ./pages/index.tsx.
Then if you'll look into the ./node_modules/next/package.json you will see that they expose built files in two ways: actual code and type defs are inside ./node_modules/next/dist/* and their re-exports are right in ./node_modules/next/*.
At least this is a real-life example and a good place to start your experiments. It doesn't mean you have to learn the whole their codebase. You just need to mimic the essencial parts of their package.json file (https://github.com/vercel/next.js/blob/canary/packages/next/package.json), specifically main, types and files in your Typescript library.
Update
Just look where absent imports could be imported from:
As you might understand, those are the places, where corresponding *.d.ts files are placed. So you just need to create reexport files in the root folder of you library and mention them in 'files' property of your lib's package.json.
The exactly similar picture I have for my own library.
I think there is no other way to impement imports of your lib the way you want, except of having either reexports or original type definitions right in the lib's root folder
This block in my package.json worked for me:
{
// ...
"files": [
"/dist"
],
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": "./dist/index.js",
"./types": "./dist/types/index.js",
"./generate": "./dist/generate/index.js"
},
"typesVersions": {
"*": {
"types": [
"./dist/types/index.d.ts"
],
"generate": [
"./dist/generate/index.d.ts"
]
}
}
}
My tsconfig.json looks like this:
{
"extends": "#tsconfig/node14/tsconfig.json",
"include": ["src/**/*"],
"compilerOptions": {
"lib": ["es2020", "dom"],
"declaration": true,
"outDir": "dist",
"module": "ESNext"
}
}
And this is my file structure:
package.json
tsconfig.json
dist/ // and all its subfolders
src/
generate/
index.ts
types/
index.ts
index.ts
Separately, I'm using TypeScript 4.7.4. Supposedly the exports field is supported with this version, but it didn't work for me. But this (maybe overly complex) workaround worked for me.
As answered in How to create a local module in TypeScript:
Using module-alias package might solve your problem.
Add this configuration below into package.json:
"_moduleAliases": { "my-module":
"<your_build_folder>/modules/my-module" },
And this code on first line
of your main file (server.ts/index.ts)
import 'module-alias/register';
I've created a React project with typescript using create-react-app version 3.4.1.
I'm trying to avoid the use of relative paths in my project. Here's a part of my project tree:
/
|_ public
|_ tests
|_ src
|____ Scenarios
|____ Components
|____c
What I basically want is to be able to to do something like import '#components/c'. I've tried to add this part to my tsconfig.json file:
{
"compilerOptions": {
...
"baseUrl": ".",
"paths": {
"*": ["src/*"],
"tests": ["tests/*"],
"public": ["public/*"],
"#components/*": ["src/Components/*"],
"#Scenarios/*": ["src/Scenarios/*"],
},
...
}
}
But every time I'm starting my app using yarn start my tsconfig deletes this part of my code (eveything but my "baseUrl" part). As far as I know since version 3 of react-create-app, solved this problem partially with enabling baseUrl property to affect the imports' root dir. But I couldn't find anywhere a working solution to set absolute paths from tsconfig path directory. The partial solution doesn't work for me as I'm probably going to import stuff from public directory.
I did try this solution from last year but it wouldn't work for me. Did anyone manage to get this or any other solution working?
Ideally the solution will enable me to still use create-react-app and not to use other packages but of course any solution would work.
you can do it with your solution by add tsconfig.extends.json and use craco or any library to custom webpack. This is my craco.config.js:
const path = require('path')
module.exports = {
webpack: {
alias: {
src: path.resolve(__dirname, './src/')
}
}
}
I am using TypeScript with React, and TypeScript is still checking libraries in node_modules folder, although I have "skipLibCheck" set to true in tsconfig.json..
Here's my tsconfig.json (I added the exclude section for troubleshooting, which also didn't work):
{
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
"module": "commonjs",
"jsx": "react",
"declaration": true,
"sourceMap": true,
"experimentalDecorators": true,
"skipLibCheck": true,
"typeRoots": [
"./node_modules/#types"
],
"types": [
"es6-promise",
"webpack-env"
],
"lib": [
"es5",
"dom",
"es2015.collection"
]
},
"exclude": [
"node_modules",
"./node_modules",
"./node_modules/*",
"./node_modules/#types/node/index.d.ts",
]
}
React version am using is 15.4.2, and TypeScript is installed globally... I had version 3.7.2, and I upgraded it to 3.7.3 because I read somewhere that skipLibCheck doesn't work with 3.7.2 ..
The error I am getting when trying to build the project with gulp is:
Error - typescript - node_modules\gsap\types\gsap-utils.d.ts(97,75): error TS1144: '{' or ';' expected
If I set skipLibCheck to false, and build the project, I'll have MANY more errors. So seems like the skipLibcheck works partially.
Any idea how to solve this? I am still new to TypeScript. Any help would be appreciated.
skipLibCheck is not meant to prevent all type checking in node_modules. Although it may work for some projects, but it's just a coincidence. You could say it works partially, true. Here's what it does:
Skip Lib Check - skipLibCheck
Skip type checking of declaration files.
This can save time during compilation at the expense of type-system
accuracy. For example, two libraries could define two copies of the
same type in an inconsistent way. Rather than doing a full check of
all d.ts files, TypeScript will type check the code you specifically
refer to in your app’s source code.
A common case where you might think to use skipLibCheck is when there
are two copies of a library’s types in your node_modules. In these
cases, you should consider using a feature like yarn’s resolutions to
ensure there is only one copy of that dependency in your tree or
investigate how to ensure there is only one copy by understanding the
dependency resolution to fix the issue without additional tooling.
skipLibCheck was introduced in Typescipt 2.0, so upgrading Typescript isn't really a fix. Yet again it may work for some people.
Now I had a case when I had to add a library using Typescript 4 to a project using Typescript 3. It was raining errors on build. Having the same version of typescript helped. The version of typescript would be specific to your project here.
The only quick solution I know is to use require instead of import (my project was backend):
import * as lib from 'lib';
const lib = require('lib');
skipLib can only skip .d.ts errors. But if you use .ts files directly from node_modules, tsc can not igonre the type errors. You may try add "// #ts-noCheck" before every .ts file in node_modules.
Here's my node script for adding // #ts-ignore before every .ts、*tsx file in node_modules. You can run it before run tsc.
// 将 node_modules 下面的每个 ts,tsx 文件头部都加上 // #ts-noCheck,以忽略 node_modules 下面的类型错误
const fs = require('fs');
const path = require('path');
const traversalPath = `./node_modules`;
function folderTraveral(filePath) {
// 根据文件路径读取文件,返回文件列表
fs.readdir(filePath, function (err, files) {
if (err) {
console.warn(err);
} else {
// 遍历读取到的文件列表
files.forEach(function (filename) {
// 获取当前文件的绝对路径
const filedir = path.join(filePath, filename);
// 根据文件路径获取文件信息,返回一个fs.Stats对象
fs.stat(filedir, function (eror, stats) {
if (eror) {
console.warn('获取文件stats失败');
} else {
const isFile = stats.isFile(); // 是文件
const isDir = stats.isDirectory(); // 是文件夹
if (
isFile &&
!filedir.endsWith('d.ts') &&
(filedir.endsWith('ts') || filedir.endsWith('tsx'))
) {
let content = fs.readFileSync(filedir, 'utf-8');
if (!content.startsWith('// #ts-nocheck')) {
content = '// #ts-nocheck \n' + content;
fs.writeFileSync(filedir, content, 'utf-8');
}
}
if (isDir) {
folderTraveral(filedir); // 递归,如果是文件夹,就继续遍历该文件夹下面的文件
}
}
});
});
}
});
}
folderTraveral(traversalPath);
Consider the following settings in jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#components/*": ["src/components/*"],
"#constants/*": ["src/constants/*"]
}
}
}
When I attempt to import app-constants.js file in my components through:
import AppConstants from "#constants/app-constants";
I seem to get the following error:
Module not found: Can't resolve '#constants/app-constants'
My app-constants.js file is located directly in the src/constants folder:
Any idea why this is happening?
EDIT
I Tried using this:
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
And works when calling directly onto the folders like constants/app-constants.js
But doesn't when I try the first method.
It would be great if someone is able to enlighten me of my mistakes.
Your code looks good and you can verify it by intellisense e.g:
import AppConstants from "#constants/";
it will show app-constants in intellisense.
Now the problem is that react is not supporting aliases yet, but will support very soon.
I don't know if we will add support for aliases anytime soon. I
personally don't have time to work on it right now. I think the
current options with setting the baseUrl to . or src is sufficient for
tackling the struggles with relative imports. Beyond that it's just
personal preference like using # instead of src as prefix.
https://github.com/facebook/create-react-app/issues/7795
Sorry everyone, I've been struggling trying to understand why I need the
/// <reference path="../typings/browser.d.ts" />
module App {
angular.module("app", [""]);
}
I'm using typings and here is my tsconfig:
{
"compilerOptions": {
"experimentalDecorators": true,
"noImplicitAny": false,
"noEmitOnError": true,
"removeComments": false,
"sourceMap": true,
"target": "es5",
"module": "commonjs"
},
"files": [
],
"exclude": [
"node_modules",
"wwwroot"
]
}
I found already several posts about, but every time a different answer and a different scenario.
I use Visual Studio 2015 with ReSharper, TypeScript 1.8.5
Once I remove <reference... tag ReSharper says "Cannot find name 'angular'" but the application runs normally. (probably because it cannot find the intellisense anymore)
Has anyone faced the same problem? Am I missing something?
From the docs on tsconfig:
If no "files" property is present in a tsconfig.json, the compiler
defaults to including all TypeScript (*.ts or *.tsx) files in the
containing directory and subdirectories. When a "files" property is
present, only the specified files are included.
You are using an empty files array ("files": []) which means no files are going to be included in the compiler context. Either add all your references to the files array, or remove the files property completely to allow the compiler to include all TS files in context.
Alternatively, you can use import and export module syntax instead.
I use one _reference.ts file with all referenced *.d.ts lybraries which I use. The typescript compiler use it information for import defenitions about js lybraries. The second case there reference are used is managing the order of ts files include into resulting js file. Another words if you add reference in file B.ts to A.ts in resulting js will be contains A.js first and B after. It's not often needed because TSC is smart and ordered file by types using but some times It's usefull then you use some suff from A.ts in B.ts dynamicly (not stronrly typed).