I'm trying to create a package with directory structure as follow:
src/
folder1/
index.ts
...
folder2/
index.ts
...
folder3/
index.ts
...
.
.
.
And I would like to import it as import { Class1 } from '#package/folder1', import { Class2 } from '#package/folder2', etc.
At this moment, I'm able to import my classes like import { Class1 } from '#package/lib/folder1'. Is it possible to achieve my expected behavior?
tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2017",
"sourceMap": true,
"outDir": "./lib",
"rootDir": "./src",
"rootDirs": ["./src/folder1"],
"lib": [
"es2017",
"esnext.asynciterable"
],
"typeRoots": [
"./node_modules/#types"
],
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"pretty": true,
"noEmit": false,
"esModuleInterop": true
},
"include": ["src"],
"exclude": ["node_modules", "lib"]
}
It seems this feature is not out-of-the-box in the version of Typescript I'm using (3.7.4). The package module-alias could be a workaround but it looks like Typescript 3.8 will allow adding aliases to the exports.
Typescript 3.8 announcement link
Related SO question
Related
I've installed #types/node
In an index.ts files, the default node modules are of type any
const fs = require('fs');
fs is any.
{
"ts-node": {
"cwd": "/Users/georgenorris/Code/take-homes/simple-chat",
"projectSearchDir": "/Users/georgenorris/Code/take-homes/simple-chat"
},
"compilerOptions": {
"typeRoots": ["./node_modules/#types"],
"lib": ["es2021"],
"module": "commonjs",
"target": "es2021",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"types": ["node"],
"sourceMap": true,
"inlineSourceMap": false,
"inlineSources": true,
"declaration": false,
"noEmit": false,
"outDir": "./.ts-node"
}
}
Is my tsconfig file
Why don't the types show up?
require('modulename') is considered a dynamic import by typescript. So doesn't think it can reliably know what types to import.
In typescript you want to use the import keyword.
import fs from 'fs'
See Playground
I have this project structure:
How to configure tsconfig.json for using paths like #app/, #server/.
I try this:
{
"compilerOptions": {
"module": "CommonJS",
"target": "es5",
"lib": [
"esnext",
"dom"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": false,
"baseUrl": "..",
"paths": {
"#app/*": [
"app/*"
],
"#server/*": [
"server/*"
]
}
},
"include": [
"."
]
}
Same config works with webpack and ts-loader, but when i run npx ts-node server/index.ts i got error:
npx ts-node server/index.ts
Error: Cannot find module '#server/a'
server/index.ts :
import a from '#server/a'
console.log('This is index.ts')
a()
Your config works for webpack because you run webpack from the project root. It does not work for server.ts because the path is relative to its directory. Try:
"paths": {
"#app/*": [
"../app/*"
],
"#server/*": [
"../server/*"
]
}
If you need to do it for both, you need two different tsconfig.json - one in the root and one in app or server.
Take a look at my project: https://github.com/mmomtchev/rlayers
It uses this feature a lot.
When attempting to compile typescript code with NodeJS using the following command:
npx ts-node src/server.ts
I receive the following error:
SyntaxError: Cannot use import statement outside a module
I followed the instructions suggested by the error:
Warning: To load an ES module, set "type": "module" in the
package.json or use the .mjs extension.
But upon following these, I still had no luck and another error was thrown instead.
Here is the content of my server.ts file.
import App from './app';
const app = new App();
app.listen(3080);
tsconfig.json contents:
{
"compileOnSave": false,
"compilerOptions": {
"target": "ES2017",
"lib": ["es2017"],
"typeRoots": ["node_modules/#types"],
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"forceConsistentCasingInFileNames": true,
"module": "commonjs",
"pretty": true,
"sourceMap": true,
"declaration": true,
"outDir": "./dist",
"allowJs": true,
"noEmit": false,
"esModuleInterop": true,
"resolveJsonModule": true,
"importHelpers": true,
"baseUrl": "src",
"skipLibCheck": true,
"paths": {
"#/*": ["*"],
}
},
"include": ["src/**/*.ts", "src/**/*.json", ".env"],
"exclude": ["node_modules"]
}
I'm not really sure what is causing this but would greatly appreciate some wisdom on the issue.
Ideally i'd like to load the app via the server.ts file, while maintaining TypeScript contents.
You may need "moduleResolution": "node" in the compilerOptions for ts to recognize these types of imports.
I have a NestJS/Typescript backend where I am trying to use two different third-party services that use different importing formats. The two are below:
PDFTron uses: const { PDFNet } = require('#pdftron/pdfnet-node');
Prisma uses: import { PrismaClient } from '#prisma/client'
I have asked PDFTron support to see if an module import style similar to Prisma works for their service, but they have told me it doesn't. So, how can I use both third parties if PDFTron doesn't work in Typescript files?
For reference, my tsconfig file contains the below:
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"baseUrl": "./",
"allowJs": true,
"skipLibCheck": false,
"strict": false,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"module": "commonjs",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"tsBuildInfoFile": ".tsbuildinfo"
},
"exclude": ["node_modules"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}
Having the below folder structure
- api
- routes
- meeting.ts
- models
- DynamoService.ts
tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"outDir": ".build",
"strict": true,
"baseUrl": "./",
"typeRoots": ["node_modules/#types"],
"types": ["node"],
"esModuleInterop": true,
"preserveConstEnums": true,
"sourceMap": true,
"allowJs": true,
"moduleResolution": "node",
"rootDir": "./",
"removeComments": true,
"noEmitOnError": true,
"noUnusedLocals": true,
"noImplicitReturns": true
},
"exclude": ["node_modules"]
}
DynamoService.ts
export class DynamoService {
...
}
meeting.ts
import { DynamoService } from 'models/DynamoService'
const dynamoService = new DynamoService()
// other Express stuff...
When testing this I receive the below runtime error
Error: Cannot find module 'models/DynamoService'
Before trying to move the functionality into a class module having some DynamoDB helper methods in meeting.ts was working just fine.
Visual Studio Code doesn't complain about anything, no compile errors.
That should be a simple task but I seem to have trouble!
There are two approaches to solve this problem.
Relative reference
You could simply change the import line like this:
import { DynamoService } from '../../models/DynamoService'
Typescript path alias
Another convenient way is to leverage this nice TypeScript feature by configuring paths in tsconfig.json:
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"models/*": ["models/*"]
},
}
See more in https://www.typescriptlang.org/tsconfig#paths or https://medium.com/slackernoon/use-typescript-aliases-to-clean-up-your-import-statements-7210b7ec2af1.