home / skills / oro-ad / nuxt-claude-devtools / typescript-strict

This skill enforces strict TypeScript practices to improve type safety in your codebase and prevent runtime errors.

npx playbooks add skill oro-ad/nuxt-claude-devtools --skill typescript-strict

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
2.0 KB
---
name: typescript-strict
description: Strict TypeScript practices. Use when writing TypeScript code to ensure type safety.
---

Enforce strict TypeScript practices:

## No `any`

Never use `any`. Use `unknown` for truly unknown types:

```typescript
// ❌ Avoid
function process(data: any) { }

// ✅ Better
function process(data: unknown) {
  if (typeof data === 'string') {
    // Now TypeScript knows it's a string
  }
}
```

## Explicit Return Types

Add explicit return types for public/exported functions:

```typescript
// ✅ Explicit return type
function calculateTotal(items: Item[]): number {
  return items.reduce((sum, item) => sum + item.price, 0)
}

// ✅ For async functions
async function fetchUser(id: string): Promise<User | null> {
  // ...
}
```

## Interface over Type

Prefer `interface` for object shapes (better error messages, extendable):

```typescript
// ✅ Prefer interface
interface User {
  id: string
  name: string
  email: string
}

// Use type for unions, primitives, or complex types
type Status = 'pending' | 'active' | 'done'
type Nullable<T> = T | null
```

## Readonly

Mark immutable data as `readonly`:

```typescript
interface Config {
  readonly apiUrl: string
  readonly maxRetries: number
}

function processItems(items: readonly Item[]) {
  // items.push() would be an error
}
```

## Type Guards

Use type guards for runtime type checking:

```typescript
function isUser(value: unknown): value is User {
  return (
    typeof value === 'object' &&
    value !== null &&
    'id' in value &&
    'name' in value
  )
}

if (isUser(data)) {
  // TypeScript knows data is User
  console.log(data.name)
}
```

## Const Assertions

Use `as const` for literal types:

```typescript
const STATUSES = ['pending', 'active', 'done'] as const
type Status = typeof STATUSES[number] // 'pending' | 'active' | 'done'
```

## Non-null Assertion

Avoid `!` when possible. Use optional chaining or type guards:

```typescript
// ❌ Risky
const name = user!.name

// ✅ Safer
const name = user?.name ?? 'Unknown'
```

Overview

This skill enforces strict TypeScript practices to improve type safety and maintainability in Vue and Nuxt projects. It guides developers away from unsafe patterns and toward explicit, extendable, and runtime-checked types. The result is fewer runtime bugs, clearer APIs, and better developer ergonomics.

How this skill works

The skill inspects TypeScript code patterns and recommends concrete replacements: avoid any, prefer unknown with guards, require explicit public return types, favor interfaces for object shapes, mark immutable data readonly, use const assertions for literal types, and avoid non-null assertions. It highlights places to add type guards and suggests safer alternatives like optional chaining and nullish coalescing.

When to use it

  • When onboarding new TypeScript developers to a codebase
  • Before merging PRs that introduce new types or public APIs
  • When converting JavaScript or loosely typed files to TypeScript
  • During code reviews to enforce consistent, strict typing
  • When building library or shared modules where API clarity matters

Best practices

  • Never use any; prefer unknown and validate with type guards
  • Add explicit return types for exported and public functions
  • Use interface for object shapes and type for unions or utilities
  • Mark immutable fields and arrays with readonly
  • Use as const for fixed literal arrays/objects to get precise union types
  • Avoid the non-null assertion (!) by using guards or optional chaining

Example use cases

  • Refactor a Nuxt composable to expose strongly typed public functions with explicit return types
  • Replace ad-hoc any usage in API response handling with unknown plus type guards
  • Define stable interfaces for shared domain models used across modules
  • Lock down configuration objects and status arrays with readonly and as const
  • Improve async data fetching by returning Promise<User | null> instead of Promise<any>

FAQ

Why avoid any entirely?

any disables TypeScript checks and can hide bugs. unknown preserves type safety by forcing explicit validation before use.

When should I use type instead of interface?

Use type for unions, mapped types, or primitives. Prefer interface for object shapes because it provides clearer errors and is extendable.