# Configure Typescript

> Use when setting up or hardening TypeScript in a frontend project — applies strict mode, additional safety flags (noUncheckedIndexedAccess, noImplicitOverride), and consistent path aliases (@/*) across tsconfig, vite, vitest, playwright, and storybook configs.

- Skill: `velimirmueller/configure-typescript` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add velimirmueller/configure-typescript`
- Raw SKILL.md: https://api.skillmd.com/api/skills/velimirmueller/configure-typescript/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: VelimirMueller (https://skillmd.com/u/velimirmueller)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/velimirmueller/configure-typescript

---


# Configure TypeScript

## 1. Audit current state

Inspect `tsconfig.json`:
- Is `compilerOptions.strict` set to `true`?
- Are `noUncheckedIndexedAccess`, `noImplicitOverride`, `noUnusedLocals`, `noUnusedParameters`, `exactOptionalPropertyTypes`, `noFallthroughCasesInSwitch`, `verbatimModuleSyntax` set?
- Is there a `paths` mapping for `@/*`?
- Is `baseUrl` set to `.`?

Inspect alias config in (whichever exist):
- `vite.config.ts` (`resolve.alias`)
- `vitest.config.ts` (`resolve.alias` or `test.alias`)
- `playwright.config.ts` (typically uses `tsconfig-paths` or no aliases)
- `.storybook/main.ts` or `.storybook/main.js`

If every flag is in place and every config has the matching alias, exit early.

## 2. Decide what to do

- Nothing strict → apply full strict + safety set.
- Strict on but missing safety flags → add them.
- Strict + flags but missing aliases somewhere → add aliases to those configs.

## 3. Update `tsconfig.json`

Apply or merge these `compilerOptions`:

```json
{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "exactOptionalPropertyTypes": true,
    "noFallthroughCasesInSwitch": true,
    "verbatimModuleSyntax": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
```

If `tsconfig.app.json` (Vite split-config) exists, apply the `paths` and safety flags there instead of the root `tsconfig.json` (Vite scaffold places app-level options in `tsconfig.app.json`).

## 4. Update `vite.config.ts`

Add `resolve.alias`:

```ts
import { defineConfig } from 'vite';
import { fileURLToPath, URL } from 'node:url';

export default defineConfig({
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
    },
  },
  // ... existing plugins
});
```

## 5. Update `vitest.config.ts` (if present)

If Vitest extends Vite config (typical), the alias is inherited. Confirm by:

```ts
import { defineConfig, mergeConfig } from 'vitest/config';
import viteConfig from './vite.config';

export default mergeConfig(viteConfig, defineConfig({
  test: { /* ... */ },
}));
```

If Vitest config is standalone (no merge), duplicate the alias block from step 4 there.

## 6. Update `.storybook/main.ts` (if Storybook installed)

Storybook 8 with Vite builder inherits Vite config. Confirm:

```ts
import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
  framework: '@storybook/react-vite',
  // ... existing options
};
export default config;
```

If Storybook uses a non-Vite builder, add a `viteFinal` hook that injects `resolve.alias`.

## 7. Update `playwright.config.ts` (if Playwright installed)

Playwright doesn't bundle the test files like Vite — it uses native Node module resolution. To support `@/*` imports in Playwright specs, install `tsconfig-paths` and register it via `globalSetup`:

```ts
// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  testDir: './tests/e2e',
  // ... existing options
});
```

```ts
// tests/setup/global-setup.ts
import { register } from 'tsconfig-paths';
import { compilerOptions } from '../../tsconfig.json';

register({
  baseUrl: '.',
  paths: compilerOptions.paths,
});
```

(Optional — many projects keep Playwright specs free of `@/*` and use plain relative imports there.)

## 8. Verify

```bash
pnpm tsc --noEmit
```

Expected: 0 errors.

Verify alias works by adding a temporary `src/__alias-check.ts`:

```ts
// src/__alias-check.ts
import App from '@/App';
console.log(App);
```

Run: `pnpm tsc --noEmit`

Expected: 0 errors.

Delete `src/__alias-check.ts` afterwards.

## References
- ./tsconfig-rules.md — every flag with rationale.
- ./path-aliases.md — alias snippets for every config file.
- ../_shared/conventions.md — `@/` prefix convention.

