Related
I have a node application that compiles typescript files to a dist folder and then serves these files as lambda resolvers via aws cdk. Here is an example of my setup:
The code
register.ts
import ValidateUserFields from '../utils/forms';
exports.main = async function (event: any, context: any) {
return {
statusCode: 200,
};
}
register-lambda-config.ts
import { Construct } from 'constructs';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as s3 from 'aws-cdk-lib/aws-s3';
export class FrontendService extends Construct {
constructor(scope: Construct, id: string) {
super(scope, id);
const api = new apigateway.RestApi(this, 'frontend-api', {
restApiName: 'Frontend Service',
description: 'This service serves the frontend.',
});
const functionName = 'register';
const handler = new lambda.Function(this, functionName, {
functionName,
runtime: lambda.Runtime.NODEJS_14_X,
code: lambda.Code.fromAsset('dist/src/lambda'),
handler: 'register.main',
});
const registerIntegration = new apigateway.LambdaIntegration(handler, {
requestTemplates: { 'application/json': '{ "statusCode": "200" }' },
});
const registerResource = api.root.addResource('register');
registerResource.addMethod('POST', registerIntegration);
}
}
tsconfig.json
{
"compilerOptions": {
"target": "ES2018",
"module": "commonjs",
"moduleResolution": "node",
"lib": ["es2018"],
"declaration": true,
"strict": true,
"noImplicitAny": false,
"strictNullChecks": true,
"noImplicitThis": true,
"alwaysStrict": true,
"esModuleInterop": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": false,
"inlineSourceMap": true,
"inlineSources": true,
"experimentalDecorators": true,
"strictPropertyInitialization": false,
"outDir": "dist",
"typeRoots": ["./node_modules/#types"]
},
"exclude": ["node_modules", "cdk.out", "./dist/**/*"]
}
And finally here is the script part of my package.json file:
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"cdk": "cdk",
"bootstrap": "cdk bootstrap",
"deploy": "cdk deploy && rimraf cdk.out",
"destroy": "cdk destroy",
"run-same-local-fe-api": "sam local start-api -p 4000 -t ./template.yaml",
"dev": "npm run build && npm run synth && concurrently --kill-others \"npm run watch\" \"npm run run-same-local-fe-api\"",
"synth": "cdk synth --no-staging > template.yaml"
},
The problem
When I run npm run dev it compiles my typescript files to the dist folder in the same structure as what I have in my src folder (where all my typescript files live). I however run into the following error if I have any imports in my register.ts file:
{"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot
find module '../utils/forms'\nRequire stack:\n-
/var/task/register.js\n- /var/runtime/UserFunction.js\n-
/var/runtime/index.js","stack":["Runtime.ImportModuleError: Error:
Cannot find module '../utils/forms'","Require stack:","-
/var/task/register.js","- /var/runtime/UserFunction.js","-
/var/runtime/index.js"," at _loadUserApp
(/var/runtime/UserFunction.js:202:13)"," at
Object.module.exports.load (/var/runtime/UserFunction.js:242:17)","
at Object. (/var/runtime/index.js:43:30)"," at
Module._compile (internal/modules/cjs/loader.js:1085:14)"," at
Object.Module._extensions..js
(internal/modules/cjs/loader.js:1114:10)"," at Module.load
(internal/modules/cjs/loader.js:950:32)"," at Function.Module._load
(internal/modules/cjs/loader.js:790:12)"," at
Function.executeUserEntryPoint [as runMain]
(internal/modules/run_main.js:75:12)"," at
internal/main/run_main_module.js:17:47"]}
This happens for imports from relative local files (like '../utils/forms' as shown in the code above) but also for imports from node_modules. When I look into the compiled register.js file in the dist folder I see that it has made an attempt to parse the import:
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const forms_1 = __importDefault(require("../utils/forms"));
const bucketName = process.env.BUCKET;
exports.main = async function (event, context) { ...
however it shows the error message above. I have tried using require instead of import but it was the same result...
Any help would be greatly appreciate! Thanks
Stated that this is really hard to answer without a minimal reproducible example; I would at least suggest to avoid any require and exports, and to use only import / export statements and following in tsconfig.json.
{
"compilerOptions": {
"module": "esnext"
}
}
Well.. I do understand that you want your main function to look something like this:
// final result written in javascript
exports.main = async function (event, context) {
return {
statusCode: 200,
};
}
But... using module.exports in Typescript is not the way to achieve that. Instead, Typescript using export directive (no s at the end of it) to define which parts of your code should be export. It's then up to your tsconfig.json file to determine which syntax will be used in order to represent this export (this is actually a part of Typescript engine)
So... a script written like this in Typescript
export async function main(event: any, context: any) {
return {
statusCode: 200,
};
}
Will be parse in Typescript as follow (I've used module: commonjs to achieve below result)
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.main = void 0;
async function main(event, context) {
return {
statusCode: 200,
};
}
exports.main = main;
//# sourceMappingURL=test.js.map
Please note how the resulted js file correctly use modile.exports and main as you intended
In short: when using Typescript, please use the language directives and let the engine to do the rest for you. This way - a single source of code can be deployed for different environment without requireing changing your app logic. Neat!
I have my express.js project in monorepo. I want to add custom path alias to it.
The directory structure is:
./
server/
----> jsconfig.json
----> .eslintrc.js
----> src/
--------> index.js
--------> modules/auth
-------------> auth.controller.js
jsconfig.json
{
"compilerOptions": {
"module": "ES6",
"baseUrl": "./",
"paths": {
"#modules/*": [
"src/modules/*"
]
}
},
"exclude": ["node_modules"]
}
.eslintrc.js
module.exports = {
env: {
es2021: true,
node: true,
},
extends: [
'airbnb-base',
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
},
rules: {
'no-console': 'error',
'no-debugger': 'error',
},
settings: {
'import/resolver': {
alias: {
map: [
['#modules/*', 'src/modules/*'],
],
extensions: ['.js', '.json'],
},
},
},
};
Simply, I just tried to import auth controller in my index.js file.
import authRoutes from '#modules/auth/auth.routes';
but I get the following error: Unable to resolve path to module '#modules/auth/auth.controller' .eslint import/no-unresolved
please, don't suggest to turn off the rule.
I've alreadyy tried eslint-import-resolver-jsconfig, but I got Cannot resolve jsConfig, SyntaxError } on 150.
Because I used monorepo, there was a problem for ESLint or even lint-staged.
So now I have only one project per repository and:
Added custom paths in jsconfig.json:
"paths": {
"#modules/*": [
"./src/modules/*"
]
}
Installed eslint-import-resolver-jsconfig and added the following configuration to the eslint.json:
"extends": [
"airbnb-base",
"eslint:recommended"
],
"plugins": ["import"],
"settings": {
"import/resolver": {
"jsconfig": {
"config": "jsconfig.json"
}
}
}
Installed the Babel plugin babel-plugin-module-resolver and added the following settings to the .babelrc:
"plugins": [
[
"module-resolver",
{
"alias": {
"#modules": "./src/modules"
}
}
]
]
But, again: This only works if you have one project per repository and all your configuration files (.*rc, package.json, etc) are in the root level.
To achieve the above I use the module-alias package.
After installing it as a normal dependency, npm i --save module-alias, add the following to your package.json:
"_moduleAliases": {
"#modules": "./src/modules"
}
That will basically define the mappings for all the aliases you want to define.
To make it work, you will now need to import the following on top of your application under index.js:
require("module-alias/register"); // If using commonJS
// or
import "module-alias/register"; // If transpiling es6
You are now all set and should be able to import your files with absolute paths looking as:
const authRoutes = require("#modules/auth/auth.routes")
// or
import authRoutes from "#modules/auth/auth.routes";
In case eslint still flags the unresolved path, you may need to update your jsconfig.json or tsconfig.json to contain the below:
"paths": {
"#modules/*": ["src/modules/*"]
}
You can find the package documentation and read more about its usage here.
I am setting a configuration to run my tests in a create-react-app + typescript app (from which I have ejected). I am using jest + enzyme. In my tsconfig.json I have set baseUrl='./src' so I can use absolute paths when I import modules. For example this is a typical import statement in one of my files:
import LayoutFlexBoxItem from 'framework/components/ui/LayoutFlexBoxItem';
You can see that the path is absolute (from /src folder) and not relative.
This works fine when I run in debug mode ( yarn start )
But when I run my test ( yarn test ), I get this error:
Cannot find module 'framework/components/Navigation' from 'index.tsx'
So it looks like jest is not able to resolve this absolute path although I have set it up in my tsconfig.json. This is my tsconfig.json:
{
"compilerOptions": {
"outDir": "dist",
"module": "esnext",
"target": "es5",
"lib": ["es6", "dom"],
"sourceMap": true,
"allowJs": true,
"jsx": "react",
"moduleResolution": "node",
"rootDir": "src",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"baseUrl": "./src"
},
"exclude": [
"node_modules",
"build",
"dist",
"config",
"scripts",
"acceptance-tests",
"webpack",
"jest",
"src/setupTests.ts"
]
}
Now I can see that there is a generated tsconfig.test.json at the root of my project. This is the ts configuration used for test. And here is its content:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs"
}
}
As you can see the "module" is commonjs here whereas in the default configuration it is esnext. Could this be one reason?
Has any one been able to unit test his typescript project with Jest and absolute path? or is this a known bug? Since I have ejected from default configuration, are there some settings to put in my webpack configuration?
Thanks for your input and suggestion.
I was struggling with the same problem and actually it turns out that a simple change seems to do the trick.
I just updated the moduleDirectories field in jest.config.js.
Before
moduleDirectories: ['node_modules']
After
moduleDirectories: ['node_modules', 'src']
As many here pointed out moduleNameMapper in jest.config.js needs to define paths specified in tsconfig.json. For example, if you have paths in tsconfig.json defined as follows
// tsconfig.json
{
...
"baseUrl": "src",
"paths": {
"#alias/*": [ 'path/to/alias/*' ]
}
...
}
then your jest.config.js needs to provide those paths in moduleNameMapper in the following format:
// jest.config.js
module.exports = {
'roots': [
'<rootDir>/src'
],
'transform': {
'^.+\\.tsx?$': 'ts-jest'
},
'moduleNameMapper': {
'#alias/(.*)': '<rootDir>/src/path/to/alias/$1'
}
};
Having that we can improve our jest.config.js to convert paths defined in tsconfig.json automatically. Here is a Gist code snippet for that:
// jest.config.js
function makeModuleNameMapper(srcPath, tsconfigPath) {
// Get paths from tsconfig
const {paths} = require(tsconfigPath).compilerOptions;
const aliases = {};
// Iterate over paths and convert them into moduleNameMapper format
Object.keys(paths).forEach((item) => {
const key = item.replace('/*', '/(.*)');
const path = paths[item][0].replace('/*', '/$1');
aliases[key] = srcPath + '/' + path;
});
return aliases;
}
const TS_CONFIG_PATH = './tsconfig.json';
const SRC_PATH = '<rootDir>/src';
module.exports = {
'roots': [
SRC_PATH
],
'transform': {
'^.+\\.tsx?$': 'ts-jest'
},
'moduleNameMapper': makeModuleNameMapper(SRC_PATH, TS_CONFIG_PATH)
};
Here is how I got moduleNameMapper working.
With the below config in my tsconfig:
"paths": {
"#App/*": [
"src/*"
],
"#Shared/*": [
"src/Shared/*"
]
},
Here's the moduleNameMapper:
"moduleNameMapper": {
"#App/(.*)": "<rootDir>/src/$1",
"#Shared/(.*)": "<rootDir>/src/Shared/$1"
}
Add this following section in your package.json. after you made the changes don't forget to restart your test watchers.
"jest": {
"moduleDirectories": [
"node_modules",
"src"
],
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"roots": [
"src"
],
"testRegex": ".spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"coverageDirectory": "../coverage",
"testEnvironment": "node",
"moduleNameMapper": {
"src/(.*)": "<rootDir>/src/$1"
}
}
For me, I just needed to add
"modulePaths": ["<rootDir>/src"],
to my jest.config.js file.
Following answer to modify moduleDirectories resulted in this error:
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Using:
modulePaths: ["node_modules", "<rootDir>/src"],
From reading the docs it appears that this a list of additional directories and so node_modules is unnecessary.
For those using an absolute path but not using named mappings, this worked for me:
# jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
}
}
# jest.config.js
const config = {
moduleDirectories: ['node_modules', '<rootDir>'],
};
Solution using the best practice
This error occurs because of using absolute paths in the import statements of our TypeScript/Nest.js/Angular projects while using Jest. Fixing it with moduleDirectories and moduleNameMapper options may solve your problem temporarily but it creates issues with other packages such as this TypeORM issue. Also, the creator of the Nest.js framework suggests that using absolute paths is a bad practice. TypeScript's official documentation recommends using relative paths for our own modules. There's also an ESLint rule that explains why absolute paths should be avoided.
Absolute path vs Relative path
import statement with absolute path looks like:
import { AuthService } from 'src/auth/auth.service'
import statement with relative path looks like:
import { AuthService } from '../auth/auth.service'
VS Code Setting
VS Code by default uses absolute path as shown above, when we auto-import using code completion or Command/Ctrl + .. We need to change this default setting to use relative paths.
Go to VS Code settings and search for a setting: Import Module Specifier. Change it from shortest to relative.
Now from here on, VS Code will automatically import using the relative paths.
Fixing imports in the project
Now in the project files, look for the absolute paths in the imports that look like the example above and delete them. You will see errors for the packages that you deleted. Simply use the auto-import suggestions and import them back. This time they will be imported using the relative paths. This step may be tedious depending on the size of your project but it's worth it in the long run.
Hope that works out! Cheers!
ts-jest can resolve this problem perfectly!
https://kulshekhar.github.io/ts-jest/docs/getting-started/paths-mapping#jest-config-with-helper
just modify jest.config.js like this:
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig.json');
module.exports = {
// preset is optional, you don't need it in case you use babel preset typescript
preset: 'ts-jest',
// note this prefix option
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, /* { prefix: '<rootDir>/' } */)
}
Here is what worked for me:
npm i -D jest typescript
npm i -D ts-jest #types/jest
npx ts-jest config:init
Then in jest.config.js, here's my setup
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
modulePaths: ["node_modules", "<rootDir>/src"],
};
in my case, I do not have any paths in tsconfig.json but I have baseUrl set to src
If you have intalled ts-jest you can use an util function called pathsToModuleNameMapper to convert the path inside tsconfig.json to your jest.config file:
My jest.config.js file:
const { join } = require('path');
const { pathsToModuleNameMapper } = require('ts-jest')
const { compilerOptions } = require('./tsconfig.json')
/** #type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
rootDir: __dirname,
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
setupFiles: ['<rootDir>/src/config/env.ts'],
collectCoverageFrom: ["<rootDir>/src/modules/**/*UseCase.ts"],
coverageProvider: "v8",
coverageThreshold: {
global: {
lines: 40
}
},
bail: true,
clearMocks: true,
displayName: 'unit-tests',
testMatch: ["<rootDir>/src/modules/**/*.spec.ts"],
preset: 'ts-jest',
testEnvironment: 'node',
modulePaths: ["<rootDir>/src"],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {
prefix: join('<rootDir>', compilerOptions.baseUrl)
})
};
I've using React with Typescript, I removed react-scripts-ts test --env=jsdom from npm test and added jest --watch as my default test, after I added jest.config.js to my project following these instructions https://basarat.gitbooks.io/typescript/docs/testing/jest.html
and I used the the configuration mentioned by #Antonie Laffargue (add/edit property moduleDirectories: ['node_modules', 'src']), it works perfectly.
I had a similar problem. I hope this could help to spare time for some of you.
My problem:
using create-react-app with typescript
using absolute paths (src/MyComp) to import components inside other components (e.g. App.tsx)
it was working on compile/run/build
it was not working on test
I found that the error was due to a different value of the NODE_PATH. So I set it on tests run.
I recreated the issue and the fix in here: https://github.com/alessandrodeste/...
I'm not sure if this could bring side effects on tests. Let me know if you have feedback ;)
You probably want moduleNameMapper feature of jest config.
It will map your custom import namespaces to real module locations.
see official documentation here:
https://facebook.github.io/jest/docs/en/configuration.html#modulenamemapper-object-string-string
If this happens to you in monorepo here's what fixed the problem for me:
Inside jest.config.js
roots: ["<rootDir>packages"],
moduleNameMapper: {
'#monopre/(.+)$': '<rootDir>packages/$1/src',
},
Assuming you have in tsconfig.json
"paths": {
"#monopre/*": ["packages/*/src"],
}
Adding the following to my jest config in package.json resolved this problem for me.
"moduleDirectories": [
"node_modules",
"src"
]
I use "baseUrl": "./" without any aliases in tsconfig.json
moduleDirectories: ['node_modules', '<rootDir>'] in jest.config.ts worked for me.
Now I can import local modules e.g import { Hello } from "src/modules/hello" without any problems.
jest.config.ts
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/configuration
*/
export default {
clearMocks: true,
collectCoverageFrom: ['**/*.(t|j)s'],
coverageDirectory: 'coverage',
coverageProvider: 'v8',
moduleDirectories: ['node_modules', '<rootDir>'],
moduleFileExtensions: ['js', 'json', 'ts'],
roots: ['src', 'test'],
setupFiles: ['dotenv/config'],
testRegex: ['.*\\.spec\\.ts$'],
transform: {
'^.+\\.(t|j)s$': 'ts-jest',
},
};
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2017",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"esModuleInterop": true,
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
"resolveJsonModule": true
},
"include": ["src/**/*", "src/**/*.json", "test/**/*"]
}
Using Svelte Kit, my solution was:
import { readFileSync } from 'fs';
import pkg from 'ts-jest/utils/index.js';
const { pathsToModuleNameMapper } = pkg;
const { compilerOptions } = JSON.parse(readFileSync('./tsconfig.json'))
export default {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['<rootDir>/**/*.test.ts'],
testPathIgnorePatterns: ['/node_modules/'],
coverageDirectory: './coverage',
coveragePathIgnorePatterns: ['node_modules'],
globals: { 'ts-jest': { diagnostics: false } },
transform: {},
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
}
I had the same problem using StitchesJS, the module was not found, the solution was to put this in my jest.config.js
moduleNameMapper: {
"stitches.config": "<rootDir>/node_modules/#stitches/react/dist/index.cjs"}
You can adapt according to the module you want.
If you have a monorepo where each project has its own tsconfig.json that extends from the base (root) tsconfig.json, and each project has its own jest.config.js, and you launch tests from the project root, you should add your moduleNameMapper to the jest.config.js in the project root.
Eg.
backend/
- tsconfig.json
- jest.config.js
frontend/
- tsconfig.json
- jest.config.js
/
- tsconfig.json
- jest.config.js
And your problem is in the jest tests frontend/ and it has a tsconfig like:
{
"compilerOptions": {
"jsx": "react-native",
"paths": {
"src/*": ["client/src/*"]
},
"noEmit": true
},
"extends": "../tsconfig.json"
}
Then adding this to the root jest.config should fix the issue:
moduleNameMapper: {
'src/(.*)': '<rootDir>/client/src/$1',
},
So in total, something like:
module.exports = {
testEnvironment: 'node',
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$',
testPathIgnorePatterns: ['cdk.out/'],
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
modulePathIgnorePatterns: ['tests'],
globals: {
'ts-jest': {
isolatedModules: true,
},
},
moduleNameMapper: {
'src/(.*)': '<rootDir>/client/src/$1',
},
};
Sort of obvious, but adding this answer since I didn't see this case in the other answers, and monorepos are still a thing :)
Kind of an old thread but recently, on top of the other suggestions of adding the paths on "moduleNameMapper": on jest.config.js and "paths": on tsconfig.json, I also had to include my test folder so the compiler could recognize it.
So on tsconfig.json, add:
...
"include": ["src", "__tests__"],
...
Hope it helps on someone googling for it 😉
I realize that there are multiple question about this, but I'm having issues finding one that matches mine, maybe someone can point me in the right direction.
In my Visual Studio project I have used package.json to download jquery typings into the node_modules folder:
{
"version": "1.0.0",
"name": "asp.net",
"private": true,
"devDependencies": {
"#syncfusion/ej2": "17.1.51",
"#syncfusion/ej2-base": "17.1.49",
"#syncfusion/ej2-data": "17.1.51",
"#syncfusion/ej2-inputs": "17.1.50",
"#syncfusion/ej2-buttons": "17.1.50",
"#syncfusion/ej2-splitbuttons": "17.1.51",
"#syncfusion/ej2-lists": "17.1.47",
"#syncfusion/ej2-navigations": "17.1.49",
"#syncfusion/ej2-popups": "17.1.50",
"#syncfusion/ej2-charts": "17.1.51",
"#syncfusion/ej2-calendars": "17.1.51",
"#syncfusion/ej2-grids": "17.1.51",
"#syncfusion/ej2-maps": "17.1.51",
"#syncfusion/ej2-pdf-export": "17.1.48",
"#syncfusion/ej2-svg-base": "17.1.48",
"#syncfusion/ej2-file-utils": "17.1.47",
"#syncfusion/ej2-compression": "17.1.47",
"#types/jquery": "3.2.0"
}
}
The actual project already uses jquery 2.1.4, but I'm thinking it shouldn't be too much of an issue if I got 3.2.0 as there wasn't a 2.1.4 available, is the types version was related to jquery script version?
My tsconfig.json has the following:
{
"compilerOptions": {
"noImplicitAny": false,
"noEmitOnError": true,
"removeComments": false,
"sourceMap": true,
"target": "es2015",
"module": "commonjs",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"baseUrl": "./",
"paths": {
"#syncfusion/ej2-base": [ "./node_modules/#syncfusion/ej2-base/dist/ej2-base.umd.min.js" ],
"#syncfusion/ej2-buttons": [ "./node_modules/#syncfusion/ej2-buttons/dist/ej2-buttons.umd.min.js" ],
"#syncfusion/ej2-popups": [ "./node_modules/#syncfusion/ej2-popups/dist/ej2-popups.umd.min.js" ],
"#syncfusion/ej2-maps": [ "./node_modules/#syncfusion/ej2-maps/dist/ej2-maps.umd.min.js" ],
"#types/jquery": [ "./node_modules/#types/jquery/index.d.ts" ]
}
},
"exclude": [
"wwwroot"
]
}
My page QBMapByState.aspx has the following javascript file QBMapByState.config.js:
System.config({
paths: {
'npm:': './node_modules/',
'syncfusion:': '../node_modules/#syncfusion/',
'types:': '../node_modules/#types/'
},
map: {
app: '../scripts/QBMapping',
//Syncfusion packages mapping
"#syncfusion/ej2-base": "syncfusion:ej2-base/dist/ej2-base.umd.min.js",
"#syncfusion/ej2-data": "syncfusion:ej2-data/dist/ej2-data.umd.min.js",
"#syncfusion/ej2-inputs": "syncfusion:ej2-inputs/dist/ej2-inputs.umd.min.js",
"#syncfusion/ej2-buttons": "syncfusion:ej2-buttons/dist/ej2-buttons.umd.min.js",
"#syncfusion/ej2-splitbuttons": "syncfusion:ej2-splitbuttons/dist/ej2-splitbuttons.umd.min.js",
"#syncfusion/ej2-lists": "syncfusion:ej2-lists/dist/ej2-lists.umd.min.js",
"#syncfusion/ej2-navigations": "syncfusion:ej2-navigations/dist/ej2-navigations.umd.min.js",
"#syncfusion/ej2-popups": "syncfusion:ej2-popups/dist/ej2-popups.umd.min.js",
"#syncfusion/ej2-charts": "syncfusion:ej2-charts/dist/ej2-charts.umd.min.js",
"#syncfusion/ej2-calendars": "syncfusion:ej2-calendars/dist/ej2-calendars.umd.min.js",
"#syncfusion/ej2-grids": "syncfusion:ej2-grids/dist/ej2-grids.umd.min.js",
"#syncfusion/ej2-maps": "syncfusion:ej2-maps/dist/ej2-maps.umd.min.js",
"#syncfusion/ej2-pdf-export": "syncfusion:ej2-pdf-export/dist/ej2-pdf-export.umd.min.js",
"#syncfusion/ej2-svg-base": "syncfusion:ej2-svg-base/dist/ej2-svg-base.umd.min.js",
"#syncfusion/ej2-file-utils": "syncfusion:ej2-file-utils/dist/ej2-file-utils.umd.min.js",
"#syncfusion/ej2-compression": "syncfusion:ej2-compression/dist/ej2-compression.umd.min.js"
},
packages: {
'app': { main: 'QBMapByState.js', defaultExtension: 'js' }
}
});
System.import('app');
I'm not sure if I need to add anything in here in regards to the type jquery.
And in my page's typescript file QBMapByState.ts I do some imports including the jquery typing like so:
import { Maps } from "#syncfusion/ej2-maps";
import { RadioButton, CheckBox, Button, ChangeEventArgs } from '#syncfusion/ej2-buttons';
import * as $ from '#types/jquery';
All but the jquery is transpiling. I get the following error:
Cannot import type declaration files. Consider importing 'jquery'
instead of '#types/jquery'
How can I get this to work? Where am I going wrong?
Debug Errors:
As the error states, you shouldn't import $ from the jquery typings, you import it from jquery itself:
import $ from "jquery";
As for your other question, there are some breaking changes between jquery 3 and jquery 2, so I'd imagine you want to use the type definitions for your jquery 2 installation:
npm install #types/jquery#2
You should add typeRoots to the tsconfig.json.
You can check it here how to use it.
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#types-typeroots-and-types
I am consistently getting the error "Cannot find module '#svgdotjs/svg.js'" in a TypeScript project, even though VSCode sees the library in node_modules just fine. Maybe I'm just completely not understanding how modules work! The library builds fine using tsc and tslint.
I'm developing a library that will render SVG's based on JSON input. I am trying to run unit tests. I am using svgdom to mock the requisite DOM container.
Abbreviated package.json:
"dependencies": {
"#svgdotjs/svg.js": "github:svgdotjs/svg.js",
},
"devDependencies": {
"chai": "^4.2.0",
"jest": "^23.6.0",
"svgdom": "0.0.18",
"ts-jest": "^23.10.5",
"ts-loader": "^5.3.3",
"ts-node": "^8.0.2",
"tslint": "^5.12.1",
"typescript": "^3.3.1",
}
ls node_modules:
Directory: D:\github\renderer\node_modules
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2019-02-01 6:01 PM .bin
d----- 2019-02-01 6:00 PM #babel
d----- 2019-02-01 6:00 PM #svgdotjs
Top of index.ts:
import SVG from "#svgdotjs/svg.js";
import Ajv from "ajv";
import { renderers } from "./renderers";
import { APRenderRep } from "./schema";
import schema from "./schema.json";
Relevant portions of of index.test.js:
import { render } from "../src/index";
test("debugging outputter", () => {
const data = {};
// As per the `svgdom` docs
const window = require("svgdom");
const {SVG, registerWindow} = require("#svgdotjs/svg.js");
registerWindow(window, window.document);
const canvas = SVG(document.documentElement);
render(canvas, data);
console.log(canvas.svg());
});
And if that weren't enough code, here's tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"target": "es2015",
"esModuleInterop": true,
"sourceMap": true,
"declaration": true,
"outDir": "build",
"resolveJsonModule": true,
"strictNullChecks": true,
"noImplicitThis": true,
"noImplicitAny": true,
"baseUrl": ".",
"paths": {
"*": [
"node_modules/*",
"src/types/*"
]
}
},
"include": [
"src/**/*"
]
}
and jest.config.js:
module.exports = {
globals: {
'ts-jest': {
tsConfig: 'tsconfig.json'
}
},
'coverageDirectory': undefined,
'collectCoverage': false,
'collectCoverageFrom': [
'**/src/**/*.{ts,js}'
],
moduleFileExtensions: [
'ts',
'js'
],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest'
},
testMatch: [
'**/test/**/*.test.(ts|js)'
],
testEnvironment: 'node'
};
I expect that the rendered SVG will magically appear on the console. Instead, I get the following:
FAIL test/index.test.ts
● Test suite failed to run
Cannot find module '#svgdotjs/svg.js' from 'index.ts'
> 1 | import SVG from "#svgdotjs/svg.js";
| ^
2 | import Ajv from "ajv";
3 | import { renderers } from "./renderers";
4 | import { APRenderRep } from "./schema";
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:221:17)
at Object.<anonymous> (src/index.ts:1:1)
I have tried nuking node_modules and reinstalling. I tried a fresh clone of the repo and installing.
The actual repo is here: https://github.com/AbstractPlay/renderer.
it seems to me that the rollup.config.js file for #svgdotjs/svg.js wasn't updated for 3.0. It has:
format: node ? 'cjs' : 'iife',
and I think it should be
format: node ? 'cjs' : 'umd',
If I change that and rebuild I am able to load it. There are still errors in the d.ts file, but at least you can get started.
In short, as of now (v3.0.11), svg.js appears to simply not work with Typescript in the way I'm using it. When I reverted to the NPM version (v2.7.1), everything worked as expected.