TypeScript can't find external module when compiled - node.js

I have a project that I based on the angular 2 seed repository (https://github.com/mgechev/angular2-seed) that I am trying to add an express server backend to written in TypeScript. My directory structure is identical, except I added a folder called server/ to src/.
I've run typings install and I can see that express.d.ts is in the typings/ directory, but for some reason when compiling my code I always get the following error (using typescript#1.8.7):
> npm start
> angular2-seed#0.0.0 start C:\Users\Cody\projects\angular2-seed
> tsc --outDir build/ --module commonjs ./src/server/server.ts && node ./build/server.js
src/server/server.ts(1,26): error TS2307: Cannot find module 'express'.
./src/server/server.ts:
import * as express from 'express';
let app = express();
app.get('/', function(req, res) {
res.send('Hello World');
});
app.listen(3000, 'localhost');
console.log('Listening on port 3000');
Strangely enough the server runs without complaining if I use ts-node
> ts-node ./src/server/server.ts
Listening on port 3000
but I'm not going to use ts-node in production for fear of performance issues (not sure if that's justified or not).
Why can't the compiler find the express external module? I'm pretty new to using TypeScript so any help is appreciated.
** EDIT **
tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true
},
"files": [
"typings/main.d.ts"
],
"exclude": [
"node_modules",
"typings/browser.d.ts",
"typings/browser/**"
],
"compileOnSave": false
}
The typings docs say that you only need to either exclude one or include the other, but I tried both and it still didn't work.

but I'm not going to use ts-node in production for fear of performance issues (not sure if that's justified or not).
Justified. Though only slightly. Its just an initial compile cost you are saving.
Why can't the compiler find the express external module?
Make sure your tsconfig.json is setup correctly to include typings/main.d.ts 🌹

It turns out the version of the typescript compiler I was using was not the one I had installed through npm, but was installed through Visual Studio and was old (version 1.0). You can check this by running where tsc.
The solution was to remove theC:\Program Files (x86)\Microsoft SDKs\TypeScript
1.0 entry from my Path env variable.
According to this GItHub issue, it looks like this is the official accepted solution.

Related

Persistent undefined error in typescript import export

There's already a LOT of questions about typescript in multiple files.. for instance, this one,
Typescript import/export
Interesting question and answer, I simplified and tested it, see below.. but whatever I try, I still get
Uncaught TypeError: Cannot read properties of undefined (reading 'A')
.. as does any other example of import/export in TypeScript I found online. Whatever I do, whatever object I try export (class, function, const) with or without using a module: I get the same error.
Maybe there is something wrong in my NPM/TSC/React configuration ? Should I change e.g. tsconfig.js when i want to use more than one typescript file in a project ? I'm lost, what do I miss ?
tsconfig.json
{ // TypeScript configuration file: provides options to the TypeScript
// compiler (tsc) and makes VSCode recognize this folder as a TS project,
// enabling the VSCode build tasks "tsc: build" and "tsc: watch".
"compilerOptions": {
"target": "es5", // Compatible with older browsers
"module": "umd", // Compatible with both Node.js and browser
"moduleResolution": "node", // Tell tsc to look in node_modules for modules
"sourceMap": true, // Creates *.js.map files
"jsx": "react", // Causes inline XML (JSX code) to be expanded
"strict": true, // Strict types, eg. prohibits `var x=0; x=null`
"alwaysStrict": true // Enable JavaScript's "use strict" mode
},
"include": ["**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
first.tsx
const A ={
val: 'A'
}
export { A }
app.tsx
import { A } from "./first";
// ... other code
function reportPerson()
{
console.log(A);
}
.. Both files translate to .js with TSC, but A is reported by the Google Chrome console as undefined,
Both tsx files are in the same directory, TSC converts them both to JS without any issue.
What's going on ?
Thanks everyone for the advice (I didn't solve the above minimal example either..)
In order to properly link my stuff together, I've now put Parcel 2 to work,
https://www.npmjs.com/package/parcel
npm i parcel
This is basically a bundler, that allows separate ts files to be concatenated after they are compiled to Javascript and it will put everything in a \dist directory,
parcel build src/index.html
Based on a small react example, I put my first "modulized" little app in TypeScript to work. Then, with the help of expert advise, I proceeded with twgl.js, which is a great toolkit for Webgl2.
npm install twgl.js
This javascript library even has sub-modules.. and everything links fine now, I can access (all of?) twgl with
import * as twgl from "./twgl-full.js";

vscode not finding type hinting for npm mssql via #types/mssql

I've been beating my head against a wall for hours on this one, it should be simple. I have a project where the node_modules are installed in a nested folder. This is a Node project with a tsconfig.json in the project root. It's not a typescript project, but I can't use typeRoots in jsconfig.json so I'm forced to use a tsconfig.json. I'm trying to get vscode to provide type hinting for the mssql package, but no matter what happens it's showing up in vscode as type any. I'm able to properly get type hinting for mocha (describe, it), node (assert), and the functions declared within the project. I'm getting type hinting for the p-memoize project when I require it (that uses d.ts file located in the project, not in #types). The difference here is that with mssql I'm using require() and it's failing with that.
Here is my tsconfig.json:
{
"compilerOptions": {
"baseUrl" : ".",
"allowJs": true,
"module": "commonjs",
"moduleResolution": "node",
"noEmit": true,
"typeRoots": ["containers/shared/node_modules/#types/"],
"paths" : {
"*": ["containers/shared/node_modules/*"],
"#simpleview/*" : ["../../containers/*"]
}
}
}
Then I have a code file with the following:
const mssql = require("mssql");
mssql is resolving as type any.
In my package.json I have the latest version of both mssql and #types/mssql:
"#types/mssql": "4.0.7",
"mssql": "6.2.1",
Am I doing something wrong here or is the #types/mssql project bugged, but if so, what exactly is wrong with it so I could submit a PR to fix it?

Use non-relative imports using TypeScript's baseurl property without WebPack

I am writing a node web application using TypeScript and Express.
I managed to get everything working, however the issue I have run into is that my imports don't seem to respect the baseUrl option of my tsconfig.json.
Here is how my tsconfig.json looks like:
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"pretty": true,
"sourceMap": true,
"target": "es6",
"outDir": "./dist",
"baseUrl": "./src"
},
"exclude": [
"node_modules"
]
}
As an example, let's say I have the following files:
- dist/
- a/
- car.js
- b/
- hat.js
In car.js I can easily require hat.js by doing:
import hat from '../../b/hat'; // relative version
This works as expected.
However, I also want to be able to do the following:
import hat from 'b/hat'; // absolute version
This does not generate any issues during compilation or shows any IDE errors, as the tsconfig.json specifies the baseUrl as ./src. Thus the above is perfectly valid TypeScript code.
However, my expectation was that the code will compile down to the relative version:
const hat = require('../../b/hat');
Unfortunatly it compiled down to:
const hat = require('b/hat');
and thus predictably does not work.
Other users have solved this issue by using 3rd party tools such as: https://github.com/s-panferov/awesome-typescript-loader
https://decembersoft.com/posts/say-goodbye-to-relative-paths-in-typescript-imports/
But majority of these tools is designed to work with WebPack, which isn't really suitable for an node back-end application. This is because we are running a long-running server, and thus won't benefit from being bundled into a single file versus several different files (unlike front-end web development).
My question is, how can I compile my TypeScript files, without WebPack, so that absolute imports works correctly.
So the way to do it is to transform back the non-relative imports to relative imports after build so that commonjs will recognize them. And the way to easily do it is the following:
Step 1: Install the transform modules:
npm i -D typescript-transform-paths
npm i -D ttypescript
Step 2: Modify tsconfig.json
"compilerOptions: {
...
"plugins": [
{ "transform": "typescript-transform-paths" },
{ "transform": "typescript-transform-paths", "afterDeclarations": true }
]
}
Step 3: Modify package.json
We will use ttypescript to build the project instead of tsc inorder to use transformers.
"build": "ttsc"
Step 4: Build and Start the project
npm run build
npm start
OP I haven't gotten this to work yet, but this article may provide some guidance: https://levelup.gitconnected.com/get-rid-of-relative-import-path-hell-in-your-typescript-project-9952adec2e84
TL;DR
yarn add link-module-alias
package.json
...
"_moduleAliases": {
"~": "dist"
}
...
My question is, how can I compile my TypeScript files, without WebPack, so that absolute imports works correctly.
My opinion
Don't. In fact don't do it even do it with webpack.
Reason
The node resolution algorithm is complicated enough : https://nodejs.org/api/modules.html#modules_all_together and doesn't need to be complicated further with "and oh, now we have baseurl".
If you still want to do it, here are your options.

How to debug TypeScript in WebStorm Node.js Remote Debug?

I have a TypeScript Node.js Restify app running inside Docker container. I can connect the WebStorm Node.js Remote Debugger, but I can only debug the compiled JS files and not the TS files.
In the tsconfig.json I have "sourceMap": true set.
Is there anything I am missing?
I have found a solution using ts-node there are a few steps that you should do for doing it.
First, you must add "esModuleInterop": true and "sourceMap": true to your tsconfig.json
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist"
},
"lib": ["es2015"]
}
After that, you should install the ts-node package.
npm i -D ts-node
The last step is adding to edit the Run/Debug Configurations of the WebStorm.
Go to Run/Debug Configurations window.
Add new Node.js configuration using the +.
Change the Node parameters to --require ts-node/register
Then, change the Javascript file to your Typescript file, for me it is: src/app.ts
Press the OK button.
Run this configuration as dubug.
What run confoguration do you use - Node.js Remote? Remote debugging with sourcemaps only works if sources are inlined (inlineSources=true in tsconfig.json)
I've had a similar issue, #lena answer didn't work for me either, but I solved the problem by adding "inlineSourceMap": true to the compilerOptions of my tsconfig.json.

Nodejs with TypeScript gives weird errors

I am using TypeScript 1.5.0-beta and I am using Visual Studio Code to create a simple Node Server using an example that Anders Hejlsberg showed at build.
///<reference path="typings/node/node.d.ts"/>
import { createServer } from "http"
export function simpleServer(port: number, message: string)
{
createServer((req, res) =>
{
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(port, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
}
I have three issues
1) With this code, whenever I try to build the ts file either using Visual Studio Code or the command $ tsc server -m commonjs, it keeps giving weird errors like these
error TS1008: Unexpected token; 'module
, class, interface, enum, import or statement' expected
2) It also tries to build node.d.ts file that I am referencing and gives additional ":" expected error messages.
3) This is more of a Visual Studio Code question. How do we get VS Code to build all ts files in a project/folder and generate js files.
I followed the instructions for the typescript setup for VS Code but I still have to individually build each ts file to gen the js code.
I know grunt is one way to do it but as far as I know VS Code should be able to build all ts files in a folder like Visual Studio does. Please correct me if I am wrong.
Thanks.
Ok, I was finally able to figure out what is going on. Since I had Visual Studio 2013 and TypeScript 1.4 installed, it created the files under C:/Program Files (x86)/Microsft SDKs/TypeScript/1.0. So, every time I use the tsc command, it was always defaulting to version 1.0.3.0 which works with TypeScript 1.4 and not 1.5.0-beta. When I install TypeScript 1.5.0-beta through node, it created the files for new version under C:\Users\Krishna V\AppData\Roaming\npm\tsc
So, for #1, to fix the compilation version issue, I changed the task.json file to use the full path for the command and windows options. So, it will look like this
{
"version": "0.1.0",
// The command is tsc.
"command": "C:\\Users\\Krishna^ V\\AppData\\Roaming\\npm\\tsc",
// Show the output window only if unrecognized errors occur.
"showOutput": "silent",
// Under windows use tsc.exe. This ensures we don't need a shell.
"windows": {
"command": "C:\\Users\\Krishna^ V\\AppData\\Roaming\\npm\\tsc"
},
// args is the HelloWorld program to compile.
"args": [],
"isShellCommand": true,
// use the standard tsc problem matcher to find compile problems
// in the output.
"problemMatcher": "$tsc"
}
For #2, seems like its a know issues with Node.d.ts being out of sync with TypeScript 1.5.0-beta and there are already similar issues with react.d.ts opened in git for this.
For #3, tsconfig.json only works with TypeScript version 1.5.0-beta and since tsc was using the wrong version, it was never using tsconfig. Now that its using the right version, its using the tsconfig and hence it builds all the files mentioned in tsconfig. For example, either of these (one with ES5 and ES6)
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"sourceMap": true,
"removeComments": true
},
"files": [
"server.ts","config.ts","models/user.ts"
]
}
OR
{
"compilerOptions": {
"target": "ES6",
"sourceMap": true,
"removeComments": true
},
"filesGlob": [
"./**/*.ts"
]
}
In this case, it will compile the three files mentioned in first option or all ts files in option 2.
1 - Module Error
This will be resolved when you move to tsconfig.json under #3 below
2 - Reference error with :
The syntax for the reference should be
import http = require('http');
3 - Automated compilation of ts files to js
Configure tsconfig.json file with your settings
(optional) turn on auto save feature in Visual Studio Code
Configure a task in Visual Studio Code
Use the watch feature in the TypeScript compiler
Here is the tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"noImplicitAny": false,
"removeComments": true,
"preserveConstEnums": true,
"target": "ES5",
"sourceMap": true,
"outDir": "../dist"
}
}
Here is a defined task .settings/tasks.json
--p specifies that you want to compile via a tsconfig.json
--w specifies that you want to recompile when files are saved
You can refer to the compiler options here
{
"version": "0.1.0",
// The command is tsc.
"command": "tsc",
// Show the output window only if unrecognized errors occur.
"showOutput": "silent",
// Under windows use tsc.exe. This ensures we don't need a shell.
"windows": {
"command": "tsc.exe"
},
// args is the HelloWorld program to compile.
"args": ["--p", "./PATH-TO-TSCONFIG-FOLDER", "--w"],
// use the standard tsc problem matcher to find compile problems
// in the output.
"problemMatcher": "$tsc"
}
Node + TypeScript = Awesome!
I can't help you with #3, as I haven't quite tried out VS Code yet. However, on #1 and #2, there are a couple things you need to do:
A.) Enable the CommonJS module type on the Typescript compiler. In Visual Studio, you would do this by going to Project --> Properties --> Typescript Build, and changing the "Module system" to "CommonJS". On the command prompt, you would do this by passing in the parameter "-module commonjs" to tsc.exe. Sorry, I don't know how to achieve this in VS Code.
B.) I think the sample code should look something like this. I'm not sure if Anders may have been giving a sneak preview of future syntax at the conference, but the following should work for you:
///<reference path="typings/node/node.d.ts"/>
import Http = require('http')
export function simpleServer(port: number, message: string)
{
Http.createServer((req, res) =>
{
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}).listen(port, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
}

Resources