Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
spillwavesolutions avatar

Mastering Typescript

  • 676 installs
  • 27 repo stars
  • Updated January 1, 2026
  • spillwavesolutions/mastering-typescript-skill

mastering-typescript is an agent skill that enforces strict TypeScript and ESLint 9 flat-config patterns for developers who want typed code with fewer runtime surprises and rigorous lint coverage.

About

mastering-typescript is a spillwavesolutions skill centered on strict TypeScript engineering with ESLint 9+ flat configuration. It provides an eslint.config.js template importing @eslint/js and typescript-eslint, enabling eslint.configs.recommended plus tseslint.configs.strictTypeChecked and tseslint.configs.stylisticTypeChecked bundles. Parser options use projectService with tsconfigRootDir set via import.meta.dirname for accurate type-aware linting across monorepos and modern ESM projects. Custom rule guidance includes conventions such as allowing unused variables only when prefixed with underscores. Developers reach for mastering-typescript when migrating from legacy .eslintrc files, tightening CI lint gates, or aligning agent-generated TypeScript with strict compiler and ESLint policies. The skill targets SaaS, API, and CLI TypeScript codebases where static analysis should catch nullability, unsafe any usage, and style drift before merge.

  • Drop-in eslint.config.js for ESLint 9+ using typescript-eslint flat config with strictTypeChecked and stylisticTypeCheck
  • Parser uses projectService and tsconfigRootDir for accurate type-aware linting without brittle project paths
  • Enforces consistent type-imports (inline-type-imports) for better tree-shaking
  • Blocks floating and misused promises, await-thenable mistakes, and nudges nullish coalescing and optional chaining
  • Unused bindings allowed only with underscore prefix via argsIgnorePattern and varsIgnorePattern

Mastering Typescript by the numbers

  • 676 all-time installs (skills.sh)
  • +16 installs in the week ending Aug 5, 2026 (Skillselion tracking)
  • Ranked #195 of 1,352 Code Review & Quality skills by installs in the Skillselion catalog
  • Security screen: MEDIUM risk (skills.sh audit)
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/spillwavesolutions/mastering-typescript-skill --skill mastering-typescript

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs676
repo stars27
Security audit3 / 3 scanners passed
Last updatedJanuary 1, 2026
Repositoryspillwavesolutions/mastering-typescript-skill

How do you configure strict TypeScript ESLint 9 flat config?

Apply strict TypeScript and ESLint 9 flat-config patterns so developers ship typed code with fewer runtime surprises.

Who is it for?

TypeScript developers adopting ESLint 9 flat config who need strict type-checked and stylistic rules enforced in CI.

Skip if: JavaScript-only codebases without TypeScript, teams staying on legacy .eslintrc without migration plans, or quick prototypes skipping strict typing.

When should I use this skill?

A developer asks for ESLint 9 flat config, typescript-eslint strict rules, eslint.config.js setup, or stricter TypeScript lint CI gates.

What you get

eslint.config.js flat configs, strictTypeChecked rule sets, and projectService-backed type-aware lint pipelines.

  • eslint.config.js flat config
  • Strict type-aware lint rule set

Files

SKILL.mdMarkdownGitHub ↗

Mastering Modern TypeScript

Build enterprise-grade, type-safe applications with TypeScript 5.9+.

Compatibility: TypeScript 5.9+, Node.js 22 LTS, Vite 7, NestJS 11, React 19

Quick Start

# Initialize TypeScript project with ESM
pnpm create vite@latest my-app --template vanilla-ts
cd my-app && pnpm install

# Configure strict TypeScript
cat > tsconfig.json << 'EOF'
{
  "compilerOptions": {
    "target": "ES2024",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}
EOF

When to Use This Skill

Use when:

  • Building type-safe React, NestJS, or Node.js applications
  • Migrating JavaScript codebases to TypeScript
  • Implementing advanced type patterns (generics, mapped types, conditional types)
  • Configuring modern TypeScript toolchains (Vite, pnpm, ESLint)
  • Designing type-safe API contracts with Zod validation
  • Comparing TypeScript approaches with Java or Python

Project Setup Checklist

Before starting any TypeScript project:

- [ ] Use pnpm for package management (faster, disk-efficient)
- [ ] Configure ESM-first (type: "module" in package.json)
- [ ] Enable strict mode in tsconfig.json
- [ ] Set up ESLint with @typescript-eslint
- [ ] Add Prettier for consistent formatting
- [ ] Configure Vitest for testing

Type System Quick Reference

Primitive Types

const name: string = "Alice";
const age: number = 30;
const active: boolean = true;
const id: bigint = 9007199254740991n;
const key: symbol = Symbol("unique");

Union and Intersection Types

// Union: value can be one of several types
type Status = "pending" | "approved" | "rejected";

// Intersection: value must satisfy all types
type Employee = Person & { employeeId: string };

// Discriminated union for type-safe handling
type Result<T> =
  | { success: true; data: T }
  | { success: false; error: string };

function handleResult<T>(result: Result<T>): T | null {
  if (result.success) {
    return result.data; // TypeScript knows data exists here
  }
  console.error(result.error);
  return null;
}

Type Guards

// typeof guard
function process(value: string | number): string {
  if (typeof value === "string") {
    return value.toUpperCase();
  }
  return value.toFixed(2);
}

// Custom type guard
interface User { type: "user"; name: string }
interface Admin { type: "admin"; permissions: string[] }

function isAdmin(person: User | Admin): person is Admin {
  return person.type === "admin";
}

The satisfies Operator (TS 5.0+)

Validate type conformance while preserving inference:

// Problem: Type assertion loses specific type info
const colors1 = {
  red: "#ff0000",
  green: "#00ff00"
} as Record<string, string>;

colors1.red.toUpperCase(); // OK, but red could be undefined

// Solution: satisfies preserves literal types
const colors2 = {
  red: "#ff0000",
  green: "#00ff00"
} satisfies Record<string, string>;

colors2.red.toUpperCase(); // OK, and TypeScript knows red exists

Generics Patterns

Basic Generic Function

function first<T>(items: T[]): T | undefined {
  return items[0];
}

const num = first([1, 2, 3]);     // number | undefined
const str = first(["a", "b"]);   // string | undefined

Constrained Generics

interface HasLength {
  length: number;
}

function logLength<T extends HasLength>(item: T): T {
  console.log(item.length);
  return item;
}

logLength("hello");     // OK: string has length
logLength([1, 2, 3]);   // OK: array has length
logLength(42);          // Error: number has no length

Generic API Response Wrapper

interface ApiResponse<T> {
  data: T;
  status: number;
  timestamp: Date;
}

async function fetchUser(id: string): Promise<ApiResponse<User>> {
  const response = await fetch(`/api/users/${id}`);
  const data = await response.json();
  return {
    data,
    status: response.status,
    timestamp: new Date()
  };
}

Utility Types Reference

TypePurposeExample
Partial<T>All properties optionalPartial<User>
Required<T>All properties requiredRequired<Config>
Pick<T, K>Select specific properties`Pick<User, "id" \
Omit<T, K>Exclude specific propertiesOmit<User, "password">
Record<K, V>Object with typed keys/valuesRecord<string, number>
ReturnType<F>Extract function return typeReturnType<typeof fn>
Parameters<F>Extract function parametersParameters<typeof fn>
Awaited<T>Unwrap Promise typeAwaited<Promise<User>>

Conditional Types

// Basic conditional type
type IsString<T> = T extends string ? true : false;

// Extract array element type
type ArrayElement<T> = T extends (infer E)[] ? E : never;

type Numbers = ArrayElement<number[]>; // number
type Strings = ArrayElement<string[]>; // string

// Practical: Extract Promise result type
type UnwrapPromise<T> = T extends Promise<infer R> ? R : T;

Mapped Types

// Make all properties readonly
type Immutable<T> = {
  readonly [K in keyof T]: T[K];
};

// Make all properties nullable
type Nullable<T> = {
  [K in keyof T]: T[K] | null;
};

// Create getter functions for each property
type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};

interface Person { name: string; age: number }
type PersonGetters = Getters<Person>;
// { getName: () => string; getAge: () => number }

Framework Integration

React with TypeScript

// Typed functional component
interface ButtonProps {
  label: string;
  onClick: () => void;
  variant?: "primary" | "secondary";
}

const Button: React.FC<ButtonProps> = ({ label, onClick, variant = "primary" }) => (
  <button className={variant} onClick={onClick}>
    {label}
  </button>
);

// Typed hooks
const [count, setCount] = useState<number>(0);
const userRef = useRef<HTMLInputElement>(null);

NestJS with TypeScript

// Type-safe DTO with class-validator
import { IsString, IsEmail, MinLength } from 'class-validator';

class CreateUserDto {
  @IsString()
  @MinLength(2)
  name: string;

  @IsEmail()
  email: string;
}

// Or with Zod (modern approach)
import { z } from 'zod';

const CreateUserSchema = z.object({
  name: z.string().min(2),
  email: z.string().email()
});

type CreateUserDto = z.infer<typeof CreateUserSchema>;

See react-integration.md and nestjs-integration.md for detailed patterns.

Validation with Zod

import { z } from 'zod';

// Define schema
const UserSchema = z.object({
  id: z.string().uuid(),
  name: z.string().min(1).max(100),
  email: z.string().email(),
  role: z.enum(["user", "admin", "moderator"]),
  createdAt: z.coerce.date()
});

// Infer TypeScript type from schema
type User = z.infer<typeof UserSchema>;

// Validate at runtime
function parseUser(data: unknown): User {
  return UserSchema.parse(data); // Throws ZodError if invalid
}

// Safe parsing (returns result object)
const result = UserSchema.safeParse(data);
if (result.success) {
  console.log(result.data); // Typed as User
} else {
  console.error(result.error.issues);
}

Modern Toolchain (2025)

ToolVersionPurpose
TypeScript5.9+Type checking and compilation
Node.js22 LTSRuntime environment
Vite7.xBuild tool and dev server
pnpm9.xPackage manager
ESLint9.xLinting with flat config
Vitest3.xTesting framework
Prettier3.xCode formatting

ESLint Flat Config (ESLint 9+)

// eslint.config.js
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  eslint.configs.recommended,
  ...tseslint.configs.strictTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  }
);

Migration Strategies

Incremental Migration

1. Add allowJs: true and checkJs: false to tsconfig.json 2. Rename files from .js to .ts one at a time 3. Add type annotations gradually 4. Enable stricter options incrementally

JSDoc for Gradual Typing

// Before full migration, use JSDoc
/**
 * @param {string} name
 * @param {number} age
 * @returns {User}
 */
function createUser(name, age) {
  return { name, age };
}

See enterprise-patterns.md for comprehensive migration guides.

Common Mistakes

MistakeProblemFix
Using any liberallyDefeats type safetyUse unknown and narrow
Ignoring strict modeMisses null/undefined bugsEnable all strict options
Type assertions (as)Can hide type errorsUse satisfies or guards
Enum for simple unionsGenerates runtime codeUse literal unions instead
Not validating API dataRuntime type mismatchesUse Zod at boundaries

Cross-Language Comparison

FeatureTypeScriptJavaPython
Type SystemStructuralNominalGradual (duck typing)
NullabilityExplicit (`T \null`)@Nullable annotations
GenericsType-level, erasedType-level, erasedRuntime via typing
InterfacesStructural matchingMust implementProtocol (3.8+)
EnumsAvoid (use unions)First-classEnum class

Reference Files

  • type-system.md — Complete type system guide
  • generics.md — Advanced generics patterns
  • enterprise-patterns.md — Error handling, validation, architecture
  • react-integration.md — React + TypeScript patterns
  • nestjs-integration.md — NestJS API development
  • toolchain.md — Modern build tools configuration

Assets

  • tsconfig-template.json — Strict enterprise config
  • eslint-template.js — ESLint 9 flat config

Scripts

  • validate-setup.sh — Verify TypeScript environment

Related skills

How it compares

Use mastering-typescript when the goal is strict ESLint 9 flat-config typing rules; use a general TypeScript tutorial skill when lint configuration is not the primary need.

FAQ

Which ESLint presets does mastering-typescript enable?

mastering-typescript enables @eslint/js recommended config plus typescript-eslint strictTypeChecked and stylisticTypeChecked bundles inside an ESLint 9+ eslint.config.js flat configuration file.

How does mastering-typescript configure type-aware linting?

mastering-typescript sets languageOptions.parserOptions.projectService to true and tsconfigRootDir to import.meta.dirname so typescript-eslint resolves project types for strict flat-config linting.

Is Mastering Typescript safe to install?

skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

Code Review & Qualityfrontendbackendtesting

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.