Tag: frontend setup

  • How to Set Up a TypeScript Project from Scratch

    How to Set Up a TypeScript Project from Scratch

    Short answer: To set up a TypeScript project from scratch, install Node.js, create a project folder, run npm init, install TypeScript as a dev dependency, create a tsconfig.json file, write your first .ts file, and compile it using npx tsc. For Node.js projects, also install @types/node.

    Key takeaways

    • Install TypeScript via npm as a dev dependency
    • Configure tsconfig.json for strict mode
    • Use separate source and dist directories
    • For Node.js, install @types/node
    • Set up a build script in package.json
    • Enable source maps for easier debugging

    You want to add static typing to your JavaScript project. TypeScript gives you that safety net without sacrificing the flexibility of JS. Setting up a TypeScript project from scratch is straightforward once you understand the moving parts. This guide takes you through a minimal yet production-ready setup using Node.js and npm.

    Terminal window showing npm install typescript command
    Run npm install –save-dev typescript to add TypeScript to your project. — Photo: 547877 / Pixabay

    Why Set Up TypeScript from Scratch?

    Using a starter template or a framework like Next.js with built-in TypeScript support is convenient, but it hides the configuration details. When you set up TypeScript from scratch, you control every option. You understand the compiler, the module system, and how types integrate with your runtime. This knowledge helps you debug configuration issues later and tailor TypeScript to your exact needs.

    Starting from scratch also teaches you the minimal requirements. You can then scale up when your project demands stricter checks or more complex builds.

    Prerequisites

    You need Node.js installed on your machine. TypeScript runs on Node, and you’ll use npm to install it. If you haven’t already, download the latest LTS version from the official Node.js website. Verify your installation by running node --version and npm --version in your terminal.

    You should also be comfortable with basic terminal commands and have a code editor ready. VS Code is a popular choice because of its first-class TypeScript support.

    Step-by-Step: Initialize the Project

    Follow these steps to create a new TypeScript project from an empty folder.

    1. Create a project folder: mkdir my-typescript-project and cd my-typescript-project.
    2. Initialize npm: Run npm init -y to create a package.json file with default values. You can edit the fields later.
    3. Install TypeScript: npm install --save-dev typescript. Installing it as a dev dependency keeps it out of production builds.
    4. Create tsconfig.json: Run npx tsc --init to generate a boilerplate configuration file.
    5. Create your first TypeScript file: Make a src directory and add index.ts inside it with a simple function.
    6. Compile: Run npx tsc to compile the TypeScript files. By default, output goes to the same directory. We’ll change that soon.

    That’s the basic setup. But a real project needs a better structure. Let’s refine it.

    Code editor showing tsconfig.json file configuration
    Configure your tsconfig.json with strict mode and output directories. — Photo: Boskampi / Pixabay

    Configuring tsconfig.json for a Real Project

    The tsconfig.json file is the heart of your TypeScript configuration. Here are the key options you’ll want to set up for a typical Node.js project.

    Strict Mode

    Enable strict: true to catch more errors at compile time. This turns on all strict type-checking options, including noImplicitAny and strictNullChecks. The earlier you catch type issues, the fewer runtime surprises you’ll have.

    Output Directory

    Set outDir to "./dist" to keep compiled JavaScript files separate from your source. Set rootDir to "./src" so TypeScript only compiles files from your source folder. This keeps your project clean.

    Module System

    For Node.js, set module to "commonjs" and target to "ES2020" or higher. This ensures your compiled code uses Node’s native module resolution.

    Source Maps

    Enable sourceMap: true to generate .map files. Source maps let you debug the original TypeScript code directly in your browser or Node debugger, rather than the compiled JavaScript.

    Sample tsconfig.json

    {
      "compilerOptions": {
        "target": "ES2020",
        "module": "commonjs",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "outDir": "./dist",
        "rootDir": "./src",
        "sourceMap": true
      },
      "include": ["src"],
      "exclude": ["node_modules", "dist"]
    }

    Integrating with Node.js

    If you’re building a Node.js application, you need type definitions for Node’s built-in modules like fs and path. Install them with npm install --save-dev @types/node. Without these, TypeScript will complain about missing types when you use require('fs') or import * as fs from 'fs'.

    Now you can write TypeScript files that use Node APIs. For example, a simple HTTP server:

    import * as http from 'http';
    
    const server = http.createServer((req, res) => {
      res.writeHead(200, { 'Content-Type': 'text/plain' });
      res.end('Hello TypeScript!');
    });
    
    server.listen(3000, () => {
      console.log('Server running on port 3000');
    });

    To run this, compile first (npx tsc) and then run the output: node dist/index.js. Or you can use ts-node to run TypeScript directly in development: npm install --save-dev ts-node and then npx ts-node src/index.ts.

    Adding a Build Script and Watch Mode

    Your package.json should include a build script so you don’t type npx tsc every time. Add these scripts:

    "scripts": {
      "build": "tsc",
      "start": "node dist/index.js",
      "dev": "ts-node src/index.ts"
    }

    For a better development experience, use TypeScript’s watch mode. Run npx tsc --watch to automatically recompile whenever you save a file. You can also add a script: "watch": "tsc --watch". This pairs well with nodemon for Node projects — nodemon restarts your server when compiled files change.

    Common Pitfalls and Best Practices

    Watch out for these common mistakes when setting up TypeScript from scratch:

    • Missing @types/node: You’ll get errors like “Cannot find name ‘require’” or “Cannot find module ‘fs’”. Install the types and set types: ["node"] in tsconfig if you want explicit control.
    • Not excluding dist from compilation: If you do not exclude the dist folder, TypeScript may compile its own output again, causing infinite loops or duplicate declarations. Add "exclude": ["node_modules", "dist"].
    • Ignoring strict mode: Skipping strict mode might let sloppy code through. It’s easier to start strict and loosen only where needed than to tighten later.
    • Forgetting esModuleInterop: Without esModuleInterop: true, importing CommonJS modules can be awkward. Enable it for a more natural import syntax.
    • Mismatched rootDir and outDir: Ensure your rootDir includes all source files. If you have files outside src, they won’t be compiled unless you adjust the include patterns.
    • Using relative paths incorrectly: When you set outDir, the folder structure inside dist mirrors the source. If your imports include deep relative paths, they still work because the structure is preserved.

    Comparison: Default vs. Production-Ready Setup

    The table below highlights the differences between a minimal TypeScript setup and one you’d use for a real project.

    FeatureDefault npx tsc –initProduction-Ready Setup
    Structural typingstrict: falsestrict: true
    Output folderSame as source./dist
    Source mapsfalsetrue
    Node type definitionsNot included@types/node installed
    Watch modeNot configuredtsc –watch script

    Managing Multiple Configuration Files

    As your project grows, you might need different TypeScript configurations for different environments. For example, you may want a stricter production build and a more lenient development build. You can create multiple tsconfig files and extend a base config. Create a tsconfig.base.json with shared options, then tsconfig.json for development and tsconfig.prod.json for production. Use the extends field:

    // tsconfig.prod.json
    {
      "extends": "./tsconfig.base.json",
      "compilerOptions": {
        "outDir": "./dist",
        "sourceMap": false
      },
      "exclude": ["node_modules", "dist", "**/*.test.ts"]
    }

    Then run npx tsc -p tsconfig.prod.json to build with the production config. This pattern keeps your configurations DRY and maintainable.

    Next Steps: Linting and Formatting

    Once your TypeScript project compiles cleanly, consider adding ESLint and Prettier. ESLint with the @typescript-eslint plugin catches code-quality issues, while Prettier enforces consistent formatting. Install them as dev dependencies and create configuration files for each. Many teams also integrate Husky to run linting before commits.

    Your setup is now ready for development. Start writing code with confidence, knowing TypeScript has your back.

    Frequently asked questions

    What is the easiest way to set up TypeScript from scratch?

    The easiest way is to install TypeScript via npm, run npx tsc –init to create a tsconfig.json, then write a .ts file and compile it. For a Node.js project, also install @types/node. Use scripts in package.json to automate builds.

    Do I need to install TypeScript globally?

    It is recommended to install TypeScript as a dev dependency per project (npm install –save-dev typescript) rather than globally. This ensures consistent versions across your team and avoids version conflicts.

    How do I configure TypeScript for Node.js?

    Set module to commonjs, target to ES2020, enable esModuleInterop, and install @types/node. Also set strict to true, outDir to ./dist, and rootDir to ./src for a clean build output.

    What is the difference between tsc and ts-node?

    tsc compiles TypeScript to JavaScript, which you then run with Node. ts-node runs TypeScript directly without a separate compile step, making it convenient for development. Use tsc for production builds and ts-node for rapid iteration.

    How do I debug TypeScript code?

    Enable source maps in tsconfig (sourceMap: true). Then you can debug the original TypeScript files using Node’s inspector (node –inspect dist/index.js) or your editor’s debugger. Tools like Visual Studio Code support breakpoints in .ts files when source maps are present.