Getting 'Module not found' although file exists - javascript

I downloaded the angular starter and ran the app and it ran well. Now I Added a new file "people.service.ts" located in "src/app/services/people.service.ts".
When I try to import it, I get an error:
Module not found: Error: Can't resolve 'services/people.service' in
'/path-to-project/angular-starter-master/src/app'
This is the code I use to import it (in src/app/app.module.ts):
import {PeopleService} from 'services/people.service';
I'm sure that there's no typos because the IDE recognizes it. There isn't any TypeScript error in the entire project. The file 'services/people.service' does contain a class named PeopleService.
Any help will be profoundly appreciated. Please let me know if you need any additional information.

The problem is that you're using absolute path instead of a relative path. Change the import to the following:
import {PeopleService} from './services/people.service';

TypeScript 2.0+
In TypeScript 2.0 you can add a baseUrl property in tsconfig.json:
{
"compilerOptions": {
"baseUrl": "."
// etc...
},
// etc...
}
Then you can import everything as if you were in the base directory:
import {PeopleService} from 'services/people.service';
On top of this, you could add a paths property, which allows you to match a pattern then map it out. For example:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"services/*": [
"services/validation/*"
]
}
// etc...
},
// etc...
}
Which would allow you to import it from anywhere like so:
import {PeopleService} from 'services/people.service';
From there, you will need to configure whatever module loader you are using to support these import names as well. Right now the TypeScript compiler doesn't seem to automatically map these out.
You can read more about this in the github issue. There is also a rootDirs property which is useful when using multiple projects.
OR
You can directly change the absolute path to relative path like this:
import {PeopleService} from './services/people.service';

Related

How can I import a file with two different custom extensions?

I have case where two files with same name but different custom extensions, for example in react native i have :
CompA.android.tsx
CompA.ios.tsx
and i want to import like this import CompA from './CompA' but i got error from typescript says: "Cannot find module './CompA' or its corresponding type declarations.".
I tried to add something in tsconfig, like this
"paths": {
"*":["src/*","*.android.tsx","*.ios.tsx"],
},
but did not work
So is there any configs i can add to make my case works?

Base path for `require()`

Note! I went through many answers before asking the question but did not find the answer I want. Please, do not mark it as a duplicate.
In es modules we can set baseUrl in jsconfig.json:
{
"compilerOptions": {
"baseUrl": "/base"
}
}
or
{
"compilerOptions": {
"baseUrl": "."
}
}
Then we can import any files from that base directory throughout the project:
import Grand from 'base/child/grands'
I want to achieve the same thing in commonjs syntax (which uses require() ). I want to be able to import files(modules) like this:
const Grand = require('base/child/grands')
not this way:
const Grand = require('./base/child/grands')
How can I achieve this?
P.S. I am working on a Next.js project which uses 'es modules' for frontend and 'commonjs' for backend.

Avoid relative path import hell in react-native?

I'm new to react-native coming from vue background, one thing I hate in react is having to use relative path imports in my components, I find myself doing something like:
import HomeScreen from '../../components/screens/HomeScreen'
If my folder structure changes it means I will have to do a search and replace in all of m components using that component, not cool and prone to be a dev hell.
Is it possible to use absolute paths like with node modules, is there a library where I can use aliases or similar, with vue I could import my components in the app.js like Vue.component('home-screen ...) and I could use them without having to import.
you can add a package.json file with a name key
{
"name": "#components"
}
in any folder and metro will recognize it.
You can then import as #components/screens/HomeScreen
If you are using vscode, you can add a jsconfig.json file to your project root to enable import autocomplete.
Here is mine:
{
"compilerOptions": {
"baseUrl": "",
"paths": {
"#components/*": ["src/components/*"],
"#helper/*": ["src/helper/*"],
"#actions/*": ["src/actions/*"],
"#constants/*": ["src/constants/*"],
"#primitives": ["src/primitives/index.js"],
"#graphql": ["src/graphql/index.js"],
"#services/*": ["src/services/*"],
"#assets/*": ["assets/*"]
}
}
}
The easy method
Add a package.json to important directories with a {"name":"<prefix>"}, similar to a monorepo.
If you are doing this, you can probably also think about making it a full monorepo since there is very little extra work
The incredibly complex method
This method is easier for using things like webpack resolver, etc.
Create a metro.config.js at the root with the following content
module.export = {
resolver: {
resolveRequest: (
context: ResolutionContext,
moduleName: string,
platform: string | null
) => {
//...
return Resolution;
}
}
}
Resolution Context
The resolution context is an object that holds attributes of the running resolution, most importantly originModulePath which is the path of the requiring module.
Resolution
The resolution is an object of either:
{ type: "empty" } for empty sources
{ type: "sourceFile", filePath: string } for JS, JSON, etc. files
{ type: "assetFiles", filePaths: string[] } for any other type (e.g. not metro compilable)
For this method, I would recommend looking at metro-resolver's types since this method is abysmally documented

Problems to import json with VueJs

So, I'm trying to import a json file to be able to set some params in my application. The code I'm using to import my json is:
import json from './json/config.json'
export default {
data() {
return {
URL_FILE_IMPORT: json.fileImport,
}
}
}
... and my config.json is very simple so far:
{
"fileImport": "<my_url_goes_here>",
}
The problem is that I'm facing this error:
ERROR Failed to compile with 1 errors
This relative module was not found:
* ./json/config.json in ./src/services/config.js
But I have access to the file, if I click in the ./json/config.json path.
I've seen that there are some differences between some vue.js versions about the json configuration. I'm not 100% sure how to see the version I'm using, but my #vue/cli-service is version 4.2.2. Does anyone knows how to solve it?
So, I've found my solution. It was very simple, I just needed to use
const jsonData = require('../json/config.json');
... and with this I can access jsonData.fileImport
Маке sure the path is correct, if you make import in file ./src/services/config.js with path "./json/data.json" it will look for json in ./src/services/json. Where exactly is your folder /json, if it is in src folder then import should be "../json/data.json". Usually there is alias in web-pack "#" which is to "/src", then import will be "#/json/config.json"

Relative import of platform specific ios/android typescript files for React-Native app

I have a component that has 2 different designs based on the platform for React-Native: MyComponent.ios.tsx and MyComponent.android.tsx.
Although when I import my component into MyView.tsx, it complains.
MyView.tsx(5,38): error TS2307: Cannot find module './MyComponent'.
I have tried to modify my tsconfig file paths to the following:
"paths": {
"*": ["*", "*.ios", "*.android"]
},
Although I still have the same problem.
Does any of you know how to resolve this problem?
Thanks
Basically this approach won't work for one reason, once your ts files are transpiled, the relative path is not there anymore for the compiler to add ".ios" or ".android" and stop complaining, so the output will not work on react-native side when reading the pure JS.
I got it working by creating a typings (MyComponent.d.ts) file in the same folder, ex:
// This file exists for two purposes:
// 1. Ensure that both ios and android files present identical types to importers.
// 2. Allow consumers to import the module as if typescript understood react-native suffixes.
import DefaultIos from './MyComponent.ios';
import * as ios from './MyComponent.ios';
import DefaultAndroid from './MyComponent.android';
import * as android from './MyComponent.android';
declare var _test: typeof ios;
declare var _test: typeof android;
declare var _testDefault: typeof DefaultIos;
declare var _testDefault: typeof DefaultAndroid;
export * from './MyComponent.ios';
Since TypeScript 4.7 there is now a new option to handle this for react native, but also web
{
"compilerOptions": {
"moduleSuffixes": [".android", ".ios", ""]
}
}
You can read more about it here:
https://www.typescriptlang.org/tsconfig#moduleSuffixes

Categories

Resources