Skip to main content
โšก Calmops

TypeScript: Installation and Setup

TypeScript: Installation and Setup

TypeScript setup is the foundation for type-safe development. This article covers installation, configuration, and development environment setup.

Introduction

TypeScript setup provides:

  • Type safety
  • Development tools
  • Build configuration
  • Project structure
  • Development workflow

Understanding TypeScript setup helps you:

  • Install TypeScript
  • Configure projects
  • Set up development environment
  • Build applications
  • Manage dependencies

Installing TypeScript

Global Installation

// โœ… Good: Install TypeScript globally
// npm install -g typescript

// Verify installation
// tsc --version

// Create a simple TypeScript file
// hello.ts
const message: string = 'Hello, TypeScript!';
console.log(message);

// Compile TypeScript
// tsc hello.ts

// Run compiled JavaScript
// node hello.js

Project Installation

// โœ… Good: Install TypeScript as project dependency
// npm install --save-dev typescript

// Create tsconfig.json
// npx tsc --init

// Or manually create tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

TypeScript Configuration

tsconfig.json

// โœ… Good: Comprehensive tsconfig.json
{
  "compilerOptions": {
    // Language and Environment
    "target": "ES2020",
    "lib": ["ES2020", "DOM"],
    "jsx": "react-jsx",

    // Module Resolution
    "module": "commonjs",
    "moduleResolution": "node",
    "baseUrl": "./src",
    "paths": {
      "@/*": ["./*"],
      "@components/*": ["./components/*"],
      "@utils/*": ["./utils/*"]
    },

    // Emit
    "outDir": "./dist",
    "rootDir": "./src",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,

    // Interop Constraints
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,

    // Type Checking
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,

    // Completeness
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

Configuration Options

// โœ… Good: Understanding key configuration options
class TypeScriptConfig {
  static options = {
    // Compilation Target
    target: {
      description: 'ECMAScript version to compile to',
      values: ['ES3', 'ES5', 'ES2015', 'ES2020', 'ES2021', 'ESNext'],
      recommended: 'ES2020'
    },

    // Module System
    module: {
      description: 'Module system to use',
      values: ['commonjs', 'es2015', 'esnext', 'amd', 'umd'],
      recommended: 'commonjs'
    },

    // Output Directory
    outDir: {
      description: 'Output directory for compiled files',
      example: './dist',
      recommended: './dist'
    },

    // Root Directory
    rootDir: {
      description: 'Root directory of source files',
      example: './src',
      recommended: './src'
    },

    // Strict Mode
    strict: {
      description: 'Enable all strict type checking options',
      values: [true, false],
      recommended: true
    },

    // Source Maps
    sourceMap: {
      description: 'Generate source map files',
      values: [true, false],
      recommended: true
    },

    // Declaration Files
    declaration: {
      description: 'Generate .d.ts files',
      values: [true, false],
      recommended: true
    }
  };

  static getRecommendedConfig() {
    return {
      target: 'ES2020',
      module: 'commonjs',
      lib: ['ES2020', 'DOM'],
      outDir: './dist',
      rootDir: './src',
      strict: true,
      sourceMap: true,
      declaration: true,
      esModuleInterop: true,
      skipLibCheck: true,
      forceConsistentCasingInFileNames: true
    };
  }
}

// Usage
const config = TypeScriptConfig.getRecommendedConfig();
console.log(config);

Development Environment Setup

VS Code Setup

// โœ… Good: VS Code configuration for TypeScript
// .vscode/settings.json
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": true
  },
  "typescript.tsdk": "node_modules/typescript/lib",
  "typescript.enablePromptUseWorkspaceTsdk": true
}

// .vscode/extensions.json
{
  "recommendations": [
    "ms-vscode.vscode-typescript-next",
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
    "orta.vscode-jest"
  ]
}

Build Tools Integration

// โœ… Good: TypeScript with build tools
// webpack.config.js
module.exports = {
  entry: './src/index.ts',
  output: {
    filename: 'bundle.js',
    path: __dirname + '/dist'
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js']
  },
  devtool: 'source-map'
};

// package.json
{
  "scripts": {
    "build": "webpack",
    "dev": "webpack serve --mode development",
    "compile": "tsc",
    "watch": "tsc --watch"
  },
  "devDependencies": {
    "typescript": "^5.0.0",
    "ts-loader": "^9.0.0",
    "webpack": "^5.0.0",
    "webpack-cli": "^5.0.0",
    "webpack-dev-server": "^4.0.0"
  }
}

Project Structure

// โœ… Good: TypeScript project structure
/*
project/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ index.ts
โ”‚   โ”œโ”€โ”€ types/
โ”‚   โ”‚   โ”œโ”€โ”€ index.ts
โ”‚   โ”‚   โ””โ”€โ”€ user.ts
โ”‚   โ”œโ”€โ”€ interfaces/
โ”‚   โ”‚   โ”œโ”€โ”€ index.ts
โ”‚   โ”‚   โ””โ”€โ”€ IUser.ts
โ”‚   โ”œโ”€โ”€ classes/
โ”‚   โ”‚   โ”œโ”€โ”€ User.ts
โ”‚   โ”‚   โ””โ”€โ”€ UserService.ts
โ”‚   โ”œโ”€โ”€ utils/
โ”‚   โ”‚   โ”œโ”€โ”€ index.ts
โ”‚   โ”‚   โ””โ”€โ”€ helpers.ts
โ”‚   โ””โ”€โ”€ services/
โ”‚       โ”œโ”€โ”€ index.ts
โ”‚       โ””โ”€โ”€ api.ts
โ”œโ”€โ”€ dist/
โ”œโ”€โ”€ tests/
โ”‚   โ””โ”€โ”€ user.test.ts
โ”œโ”€โ”€ tsconfig.json
โ”œโ”€โ”€ package.json
โ””โ”€โ”€ README.md
*/

class ProjectStructure {
  static create() {
    const structure = {
      src: {
        'index.ts': 'Entry point',
        types: 'Type definitions',
        interfaces: 'Interface definitions',
        classes: 'Class implementations',
        utils: 'Utility functions',
        services: 'Service classes'
      },
      dist: 'Compiled output',
      tests: 'Test files',
      'tsconfig.json': 'TypeScript configuration',
      'package.json': 'Project metadata'
    };

    return structure;
  }
}

Running TypeScript

Compilation

// โœ… Good: Compile TypeScript
// Single file
// tsc hello.ts

// Entire project
// tsc

// Watch mode
// tsc --watch

// With specific config
// tsc --project tsconfig.json

class TypeScriptCompiler {
  static async compile() {
    const { execSync } = require('child_process');

    try {
      // Compile TypeScript
      execSync('tsc', { stdio: 'inherit' });
      console.log('โœ… Compilation successful');
    } catch (error) {
      console.error('โŒ Compilation failed:', error.message);
    }
  }

  static async watch() {
    const { execSync } = require('child_process');

    try {
      // Watch for changes
      execSync('tsc --watch', { stdio: 'inherit' });
    } catch (error) {
      console.error('Error:', error.message);
    }
  }

  static async checkTypes() {
    const { execSync } = require('child_process');

    try {
      // Check types without emitting
      execSync('tsc --noEmit', { stdio: 'inherit' });
      console.log('โœ… Type checking passed');
    } catch (error) {
      console.error('โŒ Type errors found');
    }
  }
}

// Usage
await TypeScriptCompiler.compile();

Running with ts-node

// โœ… Good: Run TypeScript directly with ts-node
// npm install -g ts-node

// Run TypeScript file directly
// ts-node src/index.ts

// Interactive REPL
// ts-node

// With configuration
// ts-node --project tsconfig.json src/index.ts

class TsNodeRunner {
  static async run(filePath) {
    const { execSync } = require('child_process');

    try {
      execSync(`ts-node ${filePath}`, { stdio: 'inherit' });
    } catch (error) {
      console.error('Error running file:', error.message);
    }
  }

  static async runWithConfig(filePath, configPath) {
    const { execSync } = require('child_process');

    try {
      execSync(`ts-node --project ${configPath} ${filePath}`, {
        stdio: 'inherit'
      });
    } catch (error) {
      console.error('Error running file:', error.message);
    }
  }
}

// Usage
await TsNodeRunner.run('src/index.ts');

Development Workflow

npm Scripts

// โœ… Good: Useful npm scripts
// package.json
{
  "scripts": {
    // Development
    "dev": "ts-node src/index.ts",
    "watch": "tsc --watch",
    "build": "tsc",

    // Production
    "start": "node dist/index.js",
    "prod": "npm run build && npm start",

    // Testing
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage",

    // Linting
    "lint": "eslint src/**/*.ts",
    "lint:fix": "eslint src/**/*.ts --fix",

    // Type checking
    "type-check": "tsc --noEmit",

    // All checks
    "check": "npm run type-check && npm run lint && npm run test"
  }
}

Development Workflow

// โœ… Good: Typical TypeScript development workflow
class DevelopmentWorkflow {
  static async setup() {
    console.log('1. Initialize project');
    // npm init -y

    console.log('2. Install TypeScript');
    // npm install --save-dev typescript

    console.log('3. Initialize tsconfig.json');
    // npx tsc --init

    console.log('4. Create src directory');
    // mkdir src

    console.log('5. Create index.ts');
    // echo 'console.log("Hello, TypeScript!");' > src/index.ts

    console.log('6. Compile and run');
    // tsc && node dist/index.js
  }

  static async develop() {
    console.log('Development workflow:');
    console.log('1. Run: npm run watch');
    console.log('2. Edit TypeScript files');
    console.log('3. Files auto-compile');
    console.log('4. Run: npm run dev');
    console.log('5. Test changes');
  }

  static async deploy() {
    console.log('Deployment workflow:');
    console.log('1. Run: npm run check');
    console.log('2. Run: npm run build');
    console.log('3. Run: npm test');
    console.log('4. Deploy dist/ folder');
  }
}

// Usage
await DevelopmentWorkflow.setup();

Practical Setup Example

Complete Project Setup

// โœ… Good: Complete TypeScript project setup
class TypeScriptProjectSetup {
  static async createProject(projectName) {
    const fs = require('fs').promises;
    const path = require('path');

    // Create project directory
    await fs.mkdir(projectName);
    process.chdir(projectName);

    // Initialize npm
    await this.initNpm();

    // Install dependencies
    await this.installDependencies();

    // Create directories
    await this.createDirectories();

    // Create configuration files
    await this.createConfigFiles();

    // Create sample files
    await this.createSampleFiles();

    console.log(`โœ… Project ${projectName} created successfully!`);
  }

  static async initNpm() {
    const { execSync } = require('child_process');
    execSync('npm init -y', { stdio: 'inherit' });
  }

  static async installDependencies() {
    const { execSync } = require('child_process');
    execSync('npm install --save-dev typescript ts-node @types/node', {
      stdio: 'inherit'
    });
  }

  static async createDirectories() {
    const fs = require('fs').promises;
    const dirs = ['src', 'dist', 'tests'];

    for (const dir of dirs) {
      await fs.mkdir(dir, { recursive: true });
    }
  }

  static async createConfigFiles() {
    const fs = require('fs').promises;

    // tsconfig.json
    const tsconfig = {
      compilerOptions: {
        target: 'ES2020',
        module: 'commonjs',
        lib: ['ES2020'],
        outDir: './dist',
        rootDir: './src',
        strict: true,
        esModuleInterop: true,
        skipLibCheck: true,
        forceConsistentCasingInFileNames: true
      },
      include: ['src/**/*'],
      exclude: ['node_modules', 'dist']
    };

    await fs.writeFile('tsconfig.json', JSON.stringify(tsconfig, null, 2));

    // .gitignore
    const gitignore = 'node_modules/\ndist/\n*.js\n*.js.map\n';
    await fs.writeFile('.gitignore', gitignore);
  }

  static async createSampleFiles() {
    const fs = require('fs').promises;

    // src/index.ts
    const index = `const message: string = 'Hello, TypeScript!';
console.log(message);
`;

    await fs.writeFile('src/index.ts', index);
  }
}

// Usage
await TypeScriptProjectSetup.createProject('my-typescript-app');

Best Practices

  1. Use strict mode:

    // โœ… Good
    "strict": true
    
    // โŒ Bad
    "strict": false
    
  2. Configure paths:

    // โœ… Good
    "baseUrl": "./src",
    "paths": {
      "@/*": ["./*"]
    }
    
    // โŒ Bad
    // No path configuration
    
  3. Use source maps:

    // โœ… Good
    "sourceMap": true
    
    // โŒ Bad
    "sourceMap": false
    

Common Mistakes

  1. Not using strict mode:

    // โŒ Bad
    "strict": false
    
    // โœ… Good
    "strict": true
    
  2. Ignoring type errors:

    // โŒ Bad
    "noImplicitAny": false
    
    // โœ… Good
    "noImplicitAny": true
    

Summary

TypeScript setup is foundational. Key takeaways:

  • Install TypeScript globally or locally
  • Configure tsconfig.json properly
  • Set up development environment
  • Use build tools
  • Organize project structure
  • Use strict mode
  • Configure paths
  • Use source maps

Next Steps

Comments