Search code examples
node.jstypescriptvisual-studiomsbuildvisual-studio-2022

How do I create a TypeScript project for NodeJS in Visual Studio 2022 (non-code)


I want to develop a nodeJS script in a Visual Studio 2022 (not Visual Studio Code) project. I have a ASP.NET Core C# project. In that project, i have a folder TypeScript. In the typescript i have several subfolders, where I develop TypeScript scripts, that are transpiled to /wwwroot/ts/<foldername>/outputname.js

Now, appart from all these JSs for the browser, I want to create one JS for nodeJS (a console test application).

I really struggle to figure out how to configure this in tsconfig.json

I have the following main.ts file:

import * as http from "http";
import * as https from "https";

const EXIT_SUCCESS = 0;
const EXIT_FAILURE = 1;


// Define the main function, and make it async
async function main(args:string[]): Promise<number>
{
    if (args.length === 0)
    {
        console.log("No arguments provides.");
    } 
    else
    {
        // Log all arguments using a for loop
        for (let i = 0; i < args.length; i++)
        {
            console.log(`Argument ${i + 1}: ${args[i]}`);
        }
    }

    // Simulate async operation, like a delay
    await new Promise(function (resolve) { setTimeout(resolve, 1000); });
    console.log("Finished ! ");
    return EXIT_SUCCESS;
}



(function ()
{
    // process.argv[0]: This represents the name or the path to the Node.js executable
    // process.argv[1]: file path of the script file being executed.

    // Process command-line arguments (starts from index 2, 
    // since first two args are 'node' and the script path)
    const args = process.argv.slice(2);

    function handleSuccess(exitCode: number)
    {
        process.exit(exitCode);
    }

    function handleError(err: any)
    {
        if (err instanceof Error)
        {
            console.error("An error occurred:", err);
            console.error("ErrorType:", err.name);
            console.error("ErrorMessage:", err.message);
            console.error("StackTrace:", err.stack);
        }
        else
            console.error("An error occurred:", err);

        process.exit(EXIT_FAILURE);
    }

    // Call the async main function
    main(args).then(handleSuccess).catch(handleError);
})();

And then I have this tsconfig.json

{
  "compileOnSave": true,

  "compilerOptions": {
    "target": "ES2015", //"target": "es5",
    //"module": "amd", // define, export, like playground
    // "module": "commonjs", // require
    "module": "Node16",
    "types": [ "node" ],

    // "module": "commonjs", // just like typescript
    // "module": "system", // System.register
    // "module": "umd", // factory, require, exports
    // "module": "esnext", // like typescript
    // "module": "none", // Object.defineProperty, require
    // "module": "commonjs",
    "lib": [
      "ES2020"
    ],

    "noImplicitAny": true,
    "noEmitOnError": true,
    "removeComments": true,
    "sourceMap": false,
    "outDir": "../../wwwroot/nodeapp",
    "rootDir": "./",
    "allowUnreachableCode": true,

    "moduleResolution": "node" // Resolve modules using Node.js rules

    //,"alwaysStrict ": true,
  },
  "exclude": [
    "node_modules",
    "wwwroot"
  ],

  "include": [
    "**/*" ]

}

Now normally, i have for the browser:

"lib": [
  "DOM",
  "ES2016",
  "ES2015.Promise",
  "ES2015.Proxy"
],

But for the NodeJS, I thought I could do something like

"lib": [
  "node",
  "ES2020"
],

and finished, but that doesn't work. It won't recognize node as a valid lib.

The only way I've found i can make this work is to put node.d.ts into my folder. And while it now finds process, it won't recognize console, although node.d.ts defines it in global. I presume this is because it does not recognize global as the global namespace. Instead searching in window or whatever.

How can I fix this, so I won't have to write global.console ? Is this typescript nuget for Visual Studio really so stupid that it does not recognize that I want to build a nodeJS app this time, and there also is no way to tell it that ?

I'd really hate to have to add anything with npm manually, as this breaks the automated build process (continuous integration system).


Solution

  • Ah, I got this myself.
    My node.d.ts was incomplete.

    First get all required d.ts files via

    git clone https://github.com/DefinitelyTyped/DefinitelyTyped
    git clone https://github.com/nodejs/undici
    

    Now copy all types from DefinitelyTyped/types/node/v20 to the a new folder nodev20 in your root project directory.
    Then, rename nodev20/index.d.ds to nodev20/node.d.ds

    Now, copy all files from /undici/undici/types to new folder nodev20/undici-types

    Then, in the undici folder, where required, add node via reference to the parent directory

    /// <reference types="../node" />
    

    Now in globals.d.ts of nodev20 folder, replace imports to undici with import * as Undici from "./undici-types/index"; and then search-and-replace import("undici-types") with Undici. .

    Done, now the nodeJS project transpiles, and you have full intellisense support for NodeJS in VS2022 without requiring npm.