Sign In Create Account
Project Setup

TypeScript Project Setup

Complete guide to configuring TypeScript projects with optimal tooling and development workflow.

Initial Setup

Start by installing TypeScript and creating the necessary configuration files.

Installation

Install TypeScript

# Global installation (for CLI access)
npm install -g typescript

# Project installation (recommended for consistent versions)
npm install --save-dev typescript @types/node

# For React projects
npm install --save-dev @types/react @types/react-dom

# For Node.js projects with additional types
npm install --save-dev @types/express @types/cors @types/jsonwebtoken

Package.json Scripts

Recommended Scripts

{
  "scripts": {
    "build": "tsc",
    "build:watch": "tsc --watch",
    "dev": "ts-node src/index.ts",
    "dev:watch": "ts-node-dev --respawn --transpile-only src/index.ts",
    "type-check": "tsc --noEmit",
    "lint": "eslint src/**/*.{ts,tsx}",
    "lint:fix": "eslint src/**/*.{ts,tsx} --fix",
    "test": "jest",
    "test:watch": "jest --watch"
  },
  "devDependencies": {
    "typescript": "^5.0.0",
    "@types/node": "^18.0.0",
    "ts-node": "^10.0.0",
    "ts-node-dev": "^2.0.0"
  }
}

TypeScript Configuration (tsconfig.json)

A well-configured tsconfig.json is crucial for type safety and development experience.

Recommended tsconfig.json

{
  "compilerOptions": {
    // Language and Environment
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "node",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    
    // Strict Type Checking
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    
    // Module Resolution
    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"],
      "@/components/*": ["src/components/*"],
      "@/utils/*": ["src/utils/*"],
      "@/types/*": ["src/types/*"]
    },
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    
    // Emit
    "outDir": "./dist",
    "rootDir": "./src",
    "removeComments": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "inlineSources": true,
    
    // Interop Constraints
    "forceConsistentCasingInFileNames": true,
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    
    // Advanced
    "skipLibCheck": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "include": [
    "src/**/*",
    "tests/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist",
    "**/*.js"
  ]
}

Key Configuration Options

  • strict: true - Enables all strict type checking options
  • noUncheckedIndexedAccess - Makes indexed access more type-safe
  • paths - Enables absolute imports for better organization
  • declaration: true - Generates .d.ts files for libraries

ESLint and Prettier Integration

Combine TypeScript with ESLint and Prettier for consistent code quality and formatting.

ESLint Configuration

Install ESLint Dependencies

npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-prettier

.eslintrc.json

{
  "env": {
    "browser": true,
    "es2022": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "@typescript-eslint/recommended",
    "@typescript-eslint/recommended-requiring-type-checking",
    "prettier"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module",
    "project": "./tsconfig.json"
  },
  "plugins": ["@typescript-eslint"],
  "rules": {
    // TypeScript specific rules
    "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
    "@typescript-eslint/no-explicit-any": "error",
    "@typescript-eslint/no-unsafe-assignment": "error",
    "@typescript-eslint/no-unsafe-call": "error",
    "@typescript-eslint/no-unsafe-member-access": "error",
    "@typescript-eslint/no-unsafe-return": "error",
    "@typescript-eslint/prefer-nullish-coalescing": "error",
    "@typescript-eslint/prefer-optional-chain": "error",
    "@typescript-eslint/consistent-type-definitions": ["error", "interface"],
    
    // General rules
    "prefer-const": "error",
    "no-var": "error",
    "object-shorthand": "error",
    "prefer-template": "error"
  }
}

Prettier Configuration

.prettierrc

{
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "es5",
  "printWidth": 100,
  "useTabs": false,
  "bracketSpacing": true,
  "arrowParens": "avoid"
}

Development Workflow

Set up an efficient development workflow with hot reloading, type checking, and testing.

Development Server

Development Setup

# Install development dependencies
npm install --save-dev ts-node-dev nodemon concurrently

# For React/Vite projects
npm install --save-dev vite @vitejs/plugin-react

Concurrent Development Scripts

{
  "scripts": {
    "dev": "concurrently \"npm:dev:server\" \"npm:type-check:watch\"",
    "dev:server": "ts-node-dev --respawn --transpile-only src/server.ts",
    "type-check:watch": "tsc --noEmit --watch",
    "build": "npm run type-check && npm run build:compile",
    "build:compile": "tsc",
    "start": "node dist/server.js"
  }
}

VS Code Configuration

.vscode/settings.json

{
  "typescript.preferences.importModuleSpecifier": "relative",
  "typescript.suggest.autoImports": true,
  "typescript.updateImportsOnFileMove.enabled": "always",
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.organizeImports": true
  },
  "eslint.validate": [
    "javascript",
    "typescript"
  ],
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

.vscode/extensions.json

{
  "recommendations": [
    "ms-vscode.vscode-typescript-next",
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
    "bradlc.vscode-tailwindcss"
  ]
}

Git Hooks with Husky

Setup Pre-commit Hooks

# Install husky and lint-staged
npm install --save-dev husky lint-staged

# Initialize husky
npx husky install

# Add pre-commit hook
npx husky add .husky/pre-commit "npx lint-staged"

package.json - Lint Staged Config

{
  "lint-staged": {
    "*.{ts,tsx}": [
      "eslint --fix",
      "prettier --write",
      "git add"
    ],
    "*.{json,md}": [
      "prettier --write",
      "git add"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "pre-push": "npm run type-check"
    }
  }
}

Project Structure

Organize your TypeScript project with a clear, scalable structure.

Recommended Project Structure

project-root/
├── src/
│   ├── components/          # React components (if applicable)
│   ├── services/           # API services and business logic
│   ├── utils/              # Utility functions
│   ├── types/              # Type definitions
│   │   ├── api.ts          # API response types
│   │   ├── user.ts         # User-related types
│   │   └── index.ts        # Barrel exports
│   ├── hooks/              # Custom React hooks (if applicable)
│   ├── constants/          # Application constants
│   ├── config/             # Configuration files
│   └── index.ts            # Entry point
├── tests/
│   ├── __mocks__/          # Jest mocks
│   ├── unit/               # Unit tests
│   └── integration/        # Integration tests
├── dist/                   # Compiled output
├── .eslintrc.json
├── .prettierrc
├── tsconfig.json
├── jest.config.js
└── package.json

Type Definition Organization

// src/types/user.ts
export interface User {
  id: string;
  name: string;
  email: string;
  role: UserRole;
}

export type UserRole = 'admin' | 'user' | 'guest';

export interface CreateUserRequest {
  name: string;
  email: string;
  role?: UserRole;
}

// src/types/api.ts
export interface ApiResponse<T> {
  data: T;
  status: 'success' | 'error';
  message?: string;
}

export interface PaginatedResponse<T> extends ApiResponse<T[]> {
  pagination: {
    page: number;
    limit: number;
    total: number;
  };
}

// src/types/index.ts - Barrel exports
export * from './user';
export * from './api';