function isCat(pet: Cat | Dog): pet is Cat {
return (pet as Cat).meow !== undefined;
}
Does TypeScript need help narrowing union types?
Implement custom type guard with is predicate
Use built-in typeof or instanceof guards
function createUserId(id: string): UserId {
return id as UserId;
}
Prevent mixing similar primitive types
function parseJson<T>(json: string): Result<T> {
try {
return { success: true, data: JSON.parse(json) };
} catch (e) {
return { success: false, error: e as Error };
}
}
Do you need explicit error handling without exceptions?
Use Result type for functional error handling
Use try-catch for traditional exception handling
const successful = results
.filter((r): r is PromiseFulfilledResult<User> => r.status === "fulfilled")
.map((r) => r.value);
for await (const item of paginate(fetchUsers)) {
console.log(item);
}
// Default export
export default class Service {}
// Re-exports
export { util } from "./util.js";
export type { UtilOptions } from "./util.js";
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.strictTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
}
);
import.meta.dirname requires Node.js 20.11+ or 21.2+ (not available in Node.js 18 LTS)
Prettier configuration for TypeScript
{
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}
export default defineConfig({
test: {
globals: true,
environment: "node",
coverage: {
provider: "v8",
reporter: ["text", "json", "html"],
},
},
});
const config: Config = {
preset: "ts-jest",
testEnvironment: "node",
roots: ["<rootDir>/src"],
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1",
},
};
export default config;
export default defineConfig({
entry: ["src/index.ts"],
format: ["cjs", "esm"],
dts: true,
clean: true,
sourcemap: true,
});
type Status = (typeof Status)[keyof typeof Status];
Source: ForceInjection/domain-driven-design-skills — distributed by TomeVault.
1---2name: typescript-ecosystem-33description: This skill should be used when the user asks to "write typescript", "typescript config", "tsconfig", "type definition", "generics", "utility types", or works with TypeScript language patterns and configuration. Provides comprehensive TypeScript ecosystem patterns and best practices. Use when this capability is needed.4---56<purpose>7Provide comprehensive patterns for TypeScript language, configuration, type system, and tooling integration.8</purpose>910<tools>11<tool>Read - Analyze tsconfig.json and TypeScript source files</tool>12<tool>Edit - Modify TypeScript configurations and source code</tool>13<tool>Bash - Run tsc, tsx, eslint, and build commands</tool>14<tool>mcp__context7__get-library-docs - Fetch latest TypeScript documentation</tool>15</tools>1617<concepts>18<concept name="strict_mode">Enable all strict checking options (strict: true) for maximum type safety</concept>19<concept name="module_resolution">nodenext for ESM Node.js, bundler for Vite/esbuild/webpack projects</concept>20<concept name="utility_types">Built-in generic types: Partial, Required, Pick, Omit, Record, Extract, Exclude, ReturnType</concept>21<concept name="type_narrowing">Use type guards (typeof, instanceof, in, custom predicates) to safely narrow union types</concept>22</concepts>2324<tsconfig>25<recommended_base>26<description>Node.js version-specific recommended configurations</description>27<mapping>28<version node="22" lts="true" target="ES2023">Current LTS - use ES2023 for stable features</version>29<version node="24" upcoming="true" target="ES2024">Upcoming - use ES2024 for latest features</version>30</mapping>31<version node="22" lts="true">32<config>33{34 "compilerOptions": {35 "target": "ES2023",36 "lib": ["ES2023"],37 "module": "nodenext",38 "moduleResolution": "nodenext",39 "strict": true,40 "esModuleInterop": true,41 "skipLibCheck": true,42 "declaration": true,43 "declarationMap": true,44 "sourceMap": true,45 "outDir": "./dist",46 "rootDir": "./src"47 },48 "include": ["src"],49 "exclude": ["node_modules", "dist"]50}51</config>52<note>Node.js 22 LTS - use ES2023 target/lib for stable features</note>53</version>54<version node="24" upcoming="true">55<config>56{57 "compilerOptions": {58 "target": "ES2024",59 "lib": ["ES2024"],60 "module": "nodenext",61 "moduleResolution": "nodenext",62 "strict": true,63 "esModuleInterop": true,64 "skipLibCheck": true,65 "declaration": true,66 "declarationMap": true,67 "sourceMap": true,68 "outDir": "./dist",69 "rootDir": "./src"70 },71 "include": ["src"],72 "exclude": ["node_modules", "dist"]73}74</config>75<note>Node.js 24 (upcoming) - use ES2024 target/lib for latest features</note>76</version>77</recommended_base>7879<strict_options>8081<option name="strict">Enables all strict type-checking options</option>82<option name="strictNullChecks">null and undefined handled explicitly</option>83<option name="strictFunctionTypes">Stricter function type checking</option>84<option name="strictBindCallApply">Check bind, call, apply methods</option>85<option name="strictPropertyInitialization">Class properties must be initialized</option>86<option name="noImplicitAny">Error on implicit any types</option>87<option name="noImplicitReturns">Error on missing return statements</option>88<option name="noImplicitThis">Error on implicit this</option>89<option name="noUncheckedIndexedAccess">Add undefined to index signatures</option>90<option name="noUnusedLocals">Error on unused local variables</option>91<option name="noUnusedParameters">Error on unused parameters</option>92</strict_options>9394<module_resolution>95<pattern name="nodenext">96<description>Modern Node.js ESM resolution (recommended)</description>97<example>98{99"compilerOptions": {100"module": "nodenext",101"moduleResolution": "nodenext"102}103}104</example>105<note>Requires "type": "module" in package.json</note>106</pattern>107108<pattern name="bundler">109<description>For projects using bundlers (Vite, esbuild, webpack)</description>110<example>111{112 "compilerOptions": {113 "module": "esnext",114 "moduleResolution": "bundler"115 }116}117</example>118</pattern>119120<pattern name="path_aliases">121<description>Import path aliases</description>122<example>123{124 "compilerOptions": {125 "baseUrl": ".",126 "paths": {127 "@/*": ["src/*"],128 "@components/*": ["src/components/*"]129 }130 }131}132</example>133<warning>baseUrl: deprecated in TS 6.0, removed in TS 7.0; prefer paths without baseUrl</warning>134<warning>moduleResolution: "node" (alias "node10"): deprecated in TS 5.x; use "nodenext" or "bundler"</warning>135<decision_tree name="when_to_use">136<question>Are you using a bundler or working with Node.js modules?</question>137<if_yes>Configure appropriate moduleResolution: bundler for bundlers, nodenext for Node.js</if_yes>138<if_no>Stick with default module resolution for simple projects</if_no>139</decision_tree>140</pattern>141</module_resolution>142143<project_references>144<description>Monorepo and incremental builds</description>145<example>146{147"compilerOptions": {148"composite": true,149"incremental": true,150"tsBuildInfoFile": ".tsbuildinfo"151},152"references": [153{ "path": "../shared" },154{ "path": "../core" }155]156}157</example>158<note>Use tsc --build for incremental compilation</note>159</project_references>160</tsconfig>161162<type_patterns>163<utility_types>164<type name="Partial<T>">Make all properties optional</type>165<type name="Required<T>">Make all properties required</type>166<type name="Readonly<T>">Make all properties readonly</type>167<type name="Record<K,V>">Object type with key K and value V</type>168<type name="Pick<T,K>">Select specific properties from T</type>169<type name="Omit<T,K>">Exclude specific properties from T</type>170<type name="Exclude<T,U>">Exclude types from union</type>171<type name="Extract<T,U>">Extract types from union</type>172<type name="NonNullable<T>">Remove null and undefined</type>173<type name="ReturnType<T>">Get function return type</type>174<type name="Parameters<T>">Get function parameter types as tuple</type>175<type name="Awaited<T>">Unwrap Promise type</type>176</utility_types>177178<generics>179<pattern name="basic">180<description>Basic generic function</description>181<example>182function identity<T>(arg: T): T {183 return arg;184}185</example>186</pattern>187188<pattern name="constraints">189<description>Generic with type constraints</description>190<example>191function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {192 return obj[key];193}194</example>195</pattern>196197<pattern name="default_type">198<description>Generic with default type parameter</description>199<example>200interface Container<T = string> {201 value: T;202}203</example>204</pattern>205206<pattern name="multiple_constraints">207<description>Multiple generic parameters with constraints</description>208<example>209function merge<T extends object, U extends object>(a: T, b: U): T & U {210 return { ...a, ...b };211}212</example>213</pattern>214</generics>215216<conditional_types>217<pattern name="basic">218<description>Basic conditional type</description>219<example>220type IsString<T> = T extends string ? true : false;221</example>222</pattern>223224<pattern name="infer">225<description>Extract types within conditional</description>226<example>227type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;228type ArrayElement<T> = T extends (infer E)[] ? E : never;229</example>230</pattern>231232<pattern name="distributive">233<description>Distributes over union types</description>234<example>235type ToArray<T> = T extends any ? T[] : never;236// ToArray<string | number> = string[] | number[]237</example>238</pattern>239</conditional_types>240241<mapped_types>242<pattern name="basic">243<description>Basic mapped type</description>244<example>245type Readonly<T> = {246readonly [P in keyof T]: T[P];247};248</example>249</pattern>250251<pattern name="key_remapping">252<description>Map keys with renaming</description>253<example>254type Getters<T> = {255 [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];256};257</example>258</pattern>259260<pattern name="filtering">261<description>Filter properties by type</description>262<example>263type OnlyStrings<T> = {264 [K in keyof T as T[K] extends string ? K : never]: T[K];265};266</example>267</pattern>268</mapped_types>269270<template_literal_types>271<pattern name="basic">272<description>Template literal type construction</description>273<example>274type EventName = `on${Capitalize<string>}`;275type Locale = `${Language}-${Country}`;276</example>277</pattern>278279<pattern name="inference">280<description>Extract parameters from template literals</description>281<example>282type ExtractRouteParams<T> = T extends `${string}:${infer Param}/${infer Rest}`283 ? Param | ExtractRouteParams<Rest>284 : T extends `${string}:${infer Param}`285 ? Param286 : never;287</example>288</pattern>289</template_literal_types>290291<type_guards>292<pattern name="typeof">293<description>Built-in typeof type guard</description>294<example>295function process(value: string | number) {296if (typeof value === "string") {297return value.toUpperCase();298}299return value.toFixed(2);300}301</example>302</pattern>303304<pattern name="instanceof">305<description>Built-in instanceof type guard</description>306<example>307function handle(error: Error | string) {308 if (error instanceof Error) {309 return error.message;310 }311 return error;312}313</example>314</pattern>315316<pattern name="custom">317<description>Custom type guard function</description>318<example>319interface Cat { meow(): void; }320interface Dog { bark(): void; }321322function isCat(pet: Cat | Dog): pet is Cat {323return (pet as Cat).meow !== undefined;324}325</example>326<decision_tree name="when_to_use">327<question>Does TypeScript need help narrowing union types?</question>328<if_yes>Implement custom type guard with is predicate</if_yes>329<if_no>Use built-in typeof or instanceof guards</if_no>330</decision_tree>331</pattern>332333<pattern name="in_operator">334<description>Property existence type guard</description>335<example>336function move(animal: Fish | Bird) {337 if ("swim" in animal) {338 animal.swim();339 } else {340 animal.fly();341 }342}343</example>344</pattern>345</type_guards>346347<branded_types>348<pattern name="branded_primitives">349<description>Nominal typing via branding</description>350<example>351type UserId = string & { readonly **brand: unique symbol };352type OrderId = string & { readonly **brand: unique symbol };353354function createUserId(id: string): UserId {355return id as UserId;356}357</example>358<note>Prevent mixing similar primitive types</note>359</pattern>360</branded_types>361362<satisfies_operator>363<pattern name="type_checking_without_widening">364<description>Type checking without widening</description>365<example>366const config = {367endpoint: "/api",368timeout: 3000,369} satisfies Record<string, string | number>;370// config.endpoint is inferred as "/api" (literal), not string371</example>372</pattern>373</satisfies_operator>374</type_patterns>375376<runtime_patterns>377<error_handling>378<pattern name="result_type">379<description>Rust-inspired Result type for error handling</description>380<example>381type Result<T, E = Error> =382| { success: true; data: T }383| { success: false; error: E };384385function parseJson<T>(json: string): Result<T> {386try {387return { success: true, data: JSON.parse(json) };388} catch (e) {389return { success: false, error: e as Error };390}391}392</example>393<decision_tree name="when_to_use">394<question>Do you need explicit error handling without exceptions?</question>395<if_yes>Use Result type for functional error handling</if_yes>396<if_no>Use try-catch for traditional exception handling</if_no>397</decision_tree>398</pattern>399400<pattern name="custom_errors">401<description>Custom error classes with additional context</description>402<example>403class ValidationError extends Error {404 constructor(405 message: string,406 public readonly field: string,407 public readonly code: string408 ) {409 super(message);410 this.name = "ValidationError";411 }412}413</example>414</pattern>415416<pattern name="error_cause">417<description>Error chaining with cause (ES2022+)</description>418<example>419try {420 await fetchData();421} catch (e) {422 throw new Error("Failed to fetch data", { cause: e });423}424</example>425</pattern>426</error_handling>427428<async_patterns>429<pattern name="promise_all">430<description>Parallel promise execution</description>431<example>432const [users, posts] = await Promise.all([433fetchUsers(),434fetchPosts(),435]);436</example>437</pattern>438439<pattern name="promise_allSettled">440<description>Handle mixed success/failure</description>441<example>442const results = await Promise.allSettled([443 fetchUser(1),444 fetchUser(2),445 fetchUser(3),446]);447448const successful = results449.filter((r): r is PromiseFulfilledResult<User> => r.status === "fulfilled")450.map((r) => r.value);451</example>452</pattern>453454<pattern name="async_iterator">455<description>Async generator for pagination</description>456<example>457async function* paginate<T>(fetchPage: (page: number) => Promise<T[]>) {458 let page = 0;459 while (true) {460 const items = await fetchPage(page++);461 if (items.length === 0) break;462 yield* items;463 }464}465466for await (const item of paginate(fetchUsers)) {467console.log(item);468}469</example>470</pattern>471</async_patterns>472473<module_patterns>474<pattern name="esm_exports">475<description>ES module export patterns</description>476<example>477// Named exports478export const helper = () => {};479export type Config = { /\* ... \_/ };480481// Default export482export default class Service {}483484// Re-exports485export { util } from "./util.js";486export type { UtilOptions } from "./util.js";487</example>488</pattern>489490<pattern name="barrel_exports">491<description>index.ts for clean imports</description>492<example>493// src/components/index.ts494export { Button } from "./Button.js";495export { Input } from "./Input.js";496export type { ButtonProps, InputProps } from "./types.js";497</example>498<warning>Can impact tree-shaking; use sparingly</warning>499</pattern>500501<pattern name="dynamic_import">502<description>Code splitting with dynamic imports</description>503<example>504const module = await import("./heavy-module.js");505module.doSomething();506</example>507</pattern>508</module_patterns>509</runtime_patterns>510511<tooling>512<eslint>513<pattern name="recommended_config">514<description>ESLint with TypeScript (flat config)</description>515<example>516// eslint.config.js517import eslint from "@eslint/js";518import tseslint from "typescript-eslint";519520export default tseslint.config(521eslint.configs.recommended,522...tseslint.configs.strictTypeChecked,523{524languageOptions: {525parserOptions: {526projectService: true,527tsconfigRootDir: import.meta.dirname,528},529},530}531);532</example>533<note>import.meta.dirname requires Node.js 20.11+ or 21.2+ (not available in Node.js 18 LTS)</note>534</pattern>535536<key_rules>537<rule name="@typescript-eslint/no-explicit-any">Prefer unknown over any</rule>538<rule name="@typescript-eslint/no-unused-vars">Detect unused variables</rule>539<rule name="@typescript-eslint/strict-boolean-expressions">Require explicit boolean conditions</rule>540<rule name="@typescript-eslint/no-floating-promises">Require awaiting promises</rule>541<rule name="@typescript-eslint/prefer-nullish-coalescing">Use ?? over ||</rule>542</key_rules>543</eslint>544545<prettier>546<pattern name="recommended_config">547<description>Prettier configuration for TypeScript</description>548<example>549{550 "semi": true,551 "singleQuote": false,552 "tabWidth": 2,553 "trailingComma": "es5",554 "printWidth": 100555}556</example>557</pattern>558</prettier>559560<testing>561<vitest>562<pattern name="config">563<description>Modern, fast test runner</description>564<example>565// vitest.config.ts566import { defineConfig } from "vitest/config";567568export default defineConfig({569test: {570globals: true,571environment: "node",572coverage: {573provider: "v8",574reporter: ["text", "json", "html"],575},576},577});578</example>579</pattern>580</vitest>581582<jest>583<pattern name="config">584<description>Jest configuration for TypeScript</description>585<example>586// jest.config.ts587import type { Config } from "jest";588589const config: Config = {590preset: "ts-jest",591testEnvironment: "node",592roots: ["<rootDir>/src"],593moduleNameMapper: {594"^@/(.\*)$": "<rootDir>/src/$1",595},596};597598export default config;599</example>600</pattern>601</jest>602</testing>603604<build_tools>605<tsc>606<tool name="tsc">607<description>TypeScript compiler commands</description>608<use_case name="compile">tsc - Compile TypeScript</use_case>609<use_case name="build">tsc --build - Incremental build (monorepo)</use_case>610<use_case name="check">tsc --noEmit - Type check only</use_case>611<use_case name="watch">tsc --watch - Watch mode</use_case>612</tool>613</tsc>614615<tsx>616<tool name="tsx">617<description>TypeScript execution with esbuild</description>618<use_case name="run">tsx src/index.ts - Run TypeScript directly</use_case>619<use_case name="watch">tsx watch src/index.ts - Watch mode</use_case>620</tool>621</tsx>622623<tsup>624<pattern name="config">625<description>Bundle TypeScript libraries</description>626<example>627// tsup.config.ts628import { defineConfig } from "tsup";629630export default defineConfig({631entry: ["src/index.ts"],632format: ["cjs", "esm"],633dts: true,634clean: true,635sourcemap: true,636});637</example>638</pattern>639</tsup>640</build_tools>641</tooling>642643<context7_integration>644<library_id>/microsoft/typescript</library_id>645<trust_score>9.9</trust_score>646<snippets>16397</snippets>647648<usage_pattern>649<step>Resolve library ID if needed (already known: /microsoft/typescript)</step>650<step>Fetch documentation with specific topic</step>651<examples>652<example topic="tsconfig">Configuration options and patterns</example>653<example topic="generics">Generic type patterns</example>654<example topic="utility types">Built-in utility types</example>655<example topic="module resolution">Module resolution strategies</example>656</examples>657</usage_pattern>658659<common_queries>660<query topic="strict mode">Strict compiler options</query>661<query topic="path mapping">Path aliases configuration</query>662<query topic="declaration files">Type declaration generation</query>663<query topic="nodenext">ESM support in Node.js</query>664</common_queries>665</context7_integration>666667<anti_patterns>668<avoid name="any_abuse">669<description>Overusing 'any' defeats type safety</description>670<instead>Use 'unknown' and narrow with type guards</instead>671</avoid>672673<avoid name="type_assertions">674<description>Excessive 'as' casts bypass type checking</description>675<instead>Use type guards or proper typing</instead>676</avoid>677678<avoid name="implicit_any">679<description>Missing type annotations with noImplicitAny disabled</description>680<instead>Enable strict mode, add explicit types</instead>681</avoid>682683<avoid name="barrel_overuse">684<description>Barrel files can hurt tree-shaking</description>685<instead>Use direct imports for large modules</instead>686</avoid>687688<avoid name="enums">689<description>Enums have runtime overhead and quirks</description>690<instead>Use const objects with 'as const'</instead>691<example>692const Status = {693 Active: "active",694 Inactive: "inactive",695} as const;696697type Status = (typeof Status)[keyof typeof Status];698</example>699</avoid>700701<avoid name="namespace">702<description>Namespaces are legacy, use ES modules</description>703<instead>Use regular imports/exports</instead>704</avoid>705706<avoid name="decorator_abuse">707<description>Decorators add complexity and are still experimental</description>708<instead>Prefer composition and higher-order functions</instead>709</avoid>710</anti_patterns>711712<best_practices>713<practice priority="critical">Enable strict mode in all projects</practice>714<practice priority="critical">Use noUncheckedIndexedAccess for safer array/object access</practice>715<practice priority="high">Prefer 'unknown' over 'any' for unknown types</practice>716<practice priority="high">Use 'satisfies' to check types without widening</practice>717<practice priority="high">Create branded types for domain primitives</practice>718<practice priority="medium">Use Result types for error handling over exceptions</practice>719<practice priority="medium">Keep type definitions close to usage</practice>720<practice priority="medium">Export types separately with 'export type'</practice>721<practice priority="medium">Use 'const' assertions for literal types</practice>722<practice priority="medium">Prefer interfaces for public APIs, types for unions/utilities</practice>723</best_practices>724725<rules priority="critical">726<rule>Enable strict mode in all TypeScript projects</rule>727<rule>Never use any without documented justification; prefer unknown</rule>728<rule>Run tsc --noEmit before committing to catch type errors</rule>729</rules>730731<rules priority="standard">732<rule>Use noUncheckedIndexedAccess for safer array/object access</rule>733<rule>Export types separately with 'export type' for clarity</rule>734<rule>Define types before implementation for better design</rule>735<rule>Use satisfies operator to check types without widening</rule>736</rules>737738<workflow>739<phase name="analyze">740<objective>Understand TypeScript code requirements</objective>741<step>1. Check tsconfig.json for project settings</step>742<step>2. Review existing type patterns in project</step>743<step>3. Identify type dependencies and imports</step>744</phase>745<phase name="implement">746<objective>Write type-safe TypeScript code</objective>747<step>1. Define types before implementation</step>748<step>2. Use strict type checking features</step>749<step>3. Follow project naming conventions</step>750</phase>751<phase name="validate">752<objective>Verify TypeScript correctness</objective>753<step>1. Run tsc --noEmit for type checking</step>754<step>2. Check with ESLint for style issues</step>755<step>3. Verify tests pass</step>756</phase>757</workflow>758759<error_escalation>760<level severity="low">761<example>Minor type inference issue</example>762<action>Add explicit type annotation</action>763</level>764<level severity="medium">765<example>Type error in implementation</example>766<action>Fix type, verify with tsc</action>767</level>768<level severity="high">769<example>Breaking type change in public API</example>770<action>Stop, present migration options to user</action>771</level>772<level severity="critical">773<example>Type safety bypass with any or type assertion</example>774<action>Block operation, require proper typing</action>775</level>776</error_escalation>777778<constraints>779<must>Enable strict mode in tsconfig.json</must>780<must>Define explicit types for public APIs</must>781<must>Use type guards for runtime type checking</must>782<avoid>Using any type without justification</avoid>783<avoid>Type assertions without validation</avoid>784<avoid>Ignoring TypeScript errors with ts-ignore</avoid>785</constraints>786787<related_agents>788<agent name="design">API design, type system architecture, and module structure planning</agent>789<agent name="execute">TypeScript implementation with strict type checking and configuration setup</agent>790<agent name="code-quality">ESLint validation, type safety checks, and best practices enforcement</agent>791</related_agents>792793<related_skills>794<skill name="serena-usage">Symbol-level navigation for type definitions and interfaces</skill>795<skill name="context7-usage">Fetch latest TypeScript compiler and tooling documentation</skill>796<skill name="investigation-patterns">Debug type errors and investigate compilation issues</skill>797</related_skills>798799---800> Source: [ForceInjection/domain-driven-design-skills](https://github.com/ForceInjection/domain-driven-design-skills) — distributed by [TomeVault](https://tomevault.io).801<!-- tomevault:4.0:skill_md:2026-05-20 -->