
typescript-ecosystem
by takeokunn
takeokunn's nixos-configuration
SKILL.md
name: TypeScript Ecosystem description: 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.
<strict_options> Enables all strict type-checking options null and undefined handled explicitly Stricter function type checking Check bind, call, apply methods Class properties must be initialized Error on implicit any types Error on missing return statements Error on implicit this Add undefined to index signatures Error on unused local variables Error on unused parameters </strict_options>
<module_resolution> Modern Node.js ESM resolution (recommended) { "compilerOptions": { "module": "nodenext", "moduleResolution": "nodenext" } } Requires "type": "module" in package.json
<pattern name="bundler">
<description>For projects using bundlers (Vite, esbuild, webpack)</description>
<example>
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "bundler"
}
}
</example>
</pattern>
<pattern name="path_aliases">
<description>Import path aliases</description>
<example>
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"]
}
}
}
</example>
<warning>baseUrl: deprecated in TS 6.0, removed in TS 7.0; prefer paths without baseUrl</warning>
<warning>moduleResolution: "node" (alias "node10"): deprecated in TS 5.x; use "nodenext" or "bundler"</warning>
<decision_tree name="when_to_use">
<question>Are you using a bundler or working with Node.js modules?</question>
<if_yes>Configure appropriate moduleResolution: bundler for bundlers, nodenext for Node.js</if_yes>
<if_no>Stick with default module resolution for simple projects</if_no>
</decision_tree>
</pattern>
</module_resolution>
<project_references> Monorepo and incremental builds { "compilerOptions": { "composite": true, "incremental": true, "tsBuildInfoFile": ".tsbuildinfo" }, "references": [ { "path": "../shared" }, { "path": "../core" } ] } Use tsc --build for incremental compilation </project_references>
<type_patterns> <utility_types> Make all properties optional Make all properties required Make all properties readonly Object type with key K and value V Select specific properties from T Exclude specific properties from T Exclude types from union Extract types from union Remove null and undefined Get function return type Get function parameter types as tuple Unwrap Promise type </utility_types>
<pattern name="constraints">
<description>Generic with type constraints</description>
<example>
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
</example>
</pattern>
<pattern name="default_type">
<description>Generic with default type parameter</description>
<example>
interface Container<T = string> {
value: T;
}
</example>
</pattern>
<pattern name="multiple_constraints">
<description>Multiple generic parameters with constraints</description>
<example>
function merge<T extends object, U extends object>(a: T, b: U): T & U {
return { ...a, ...b };
}
</example>
</pattern>
<conditional_types> Basic conditional type type IsString<T> = T extends string ? true : false;
<pattern name="infer">
<description>Extract types within conditional</description>
<example>
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type ArrayElement<T> = T extends (infer E)[] ? E : never;
</example>
</pattern>
<pattern name="distributive">
<description>Distributes over union types</description>
<example>
type ToArray<T> = T extends any ? T[] : never;
// ToArray<string | number> = string[] | number[]
</example>
</pattern>
</conditional_types>
<mapped_types> Basic mapped type type Readonly<T> = { readonly [P in keyof T]: T[P]; };
<pattern name="key_remapping">
<description>Map keys with renaming</description>
<example>
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
</example>
</pattern>
<pattern name="filtering">
<description>Filter properties by type</description>
<example>
type OnlyStrings<T> = {
[K in keyof T as T[K] extends string ? K : never]: T[K];
};
</example>
</pattern>
</mapped_types>
<template_literal_types>
Template literal type construction
type EventName = on${Capitalize<string>};
type Locale = ${Language}-${Country};
<pattern name="inference">
<description>Extract parameters from template literals</description>
<example>
type ExtractRouteParams<T> = T extends `${string}:${infer Param}/${infer Rest}`
? Param | ExtractRouteParams<Rest>
: T extends `${string}:${infer Param}`
? Param
: never;
</example>
</pattern>
</template_literal_types>
<type_guards> Built-in typeof type guard function process(value: string | number) { if (typeof value === "string") { return value.toUpperCase(); } return value.toFixed(2); }
<pattern name="instanceof">
<description>Built-in instanceof type guard</description>
<example>
function handle(error: Error | string) {
if (error instanceof Error) {
return error.message;
}
return error;
}
</example>
</pattern>
<pattern name="custom">
<description>Custom type guard function</description>
<example>
interface Cat { meow(): void; }
interface Dog { bark(): void; }
function isCat(pet: Cat | Dog): pet is Cat {
return (pet as Cat).meow !== undefined;
}
</example>
<decision_tree name="when_to_use">
<question>Does TypeScript need help narrowing union types?</question>
<if_yes>Implement custom type guard with is predicate</if_yes>
<if_no>Use built-in typeof or instanceof guards</if_no>
</decision_tree>
</pattern>
<pattern name="in_operator">
<description>Property existence type guard</description>
<example>
function move(animal: Fish | Bird) {
if ("swim" in animal) {
animal.swim();
} else {
animal.fly();
}
}
</example>
</pattern>
</type_guards>
<branded_types> Nominal typing via branding type UserId = string & { readonly **brand: unique symbol }; type OrderId = string & { readonly **brand: unique symbol };
function createUserId(id: string): UserId {
return id as UserId;
}
</example>
<note>Prevent mixing similar primitive types</note>
</pattern>
</branded_types>
<satisfies_operator> Type checking without widening const config = { endpoint: "/api", timeout: 3000, } satisfies Record<string, string | number>; // config.endpoint is inferred as "/api" (literal), not string </satisfies_operator> </type_patterns>
<runtime_patterns> <error_handling> Rust-inspired Result type for error handling type Result<T, E = Error> = | { success: true; data: T } | { success: false; error: E };
function parseJson<T>(json: string): Result<T> {
try {
return { success: true, data: JSON.parse(json) };
} catch (e) {
return { success: false, error: e as Error };
}
}
</example>
<decision_tree name="when_to_use">
<question>Do you need explicit error handling without exceptions?</question>
<if_yes>Use Result type for functional error handling</if_yes>
<if_no>Use try-catch for traditional exception handling</if_no>
</decision_tree>
</pattern>
<pattern name="custom_errors">
<description>Custom error classes with additional context</description>
<example>
class ValidationError extends Error {
constructor(
message: string,
public readonly field: string,
public readonly code: string
) {
super(message);
this.name = "ValidationError";
}
}
</example>
</pattern>
<pattern name="error_cause">
<description>Error chaining with cause (ES2022+)</description>
<example>
try {
await fetchData();
} catch (e) {
throw new Error("Failed to fetch data", { cause: e });
}
</example>
</pattern>
</error_handling>
<async_patterns> Parallel promise execution const [users, posts] = await Promise.all([ fetchUsers(), fetchPosts(), ]);
<pattern name="promise_allSettled">
<description>Handle mixed success/failure</description>
<example>
const results = await Promise.allSettled([
fetchUser(1),
fetchUser(2),
fetchUser(3),
]);
const successful = results
.filter((r): r is PromiseFulfilledResult<User> => r.status === "fulfilled")
.map((r) => r.value);
</example>
</pattern>
<pattern name="async_iterator">
<description>Async generator for pagination</description>
<example>
async function* paginate<T>(fetchPage: (page: number) => Promise<T[]>) {
let page = 0;
while (true) {
const items = await fetchPage(page++);
if (items.length === 0) break;
yield* items;
}
}
for await (const item of paginate(fetchUsers)) {
console.log(item);
}
</example>
</pattern>
</async_patterns>
<module_patterns> ES module export patterns // Named exports export const helper = () => {}; export type Config = { /* ... _/ };
// Default export
export default class Service {}
// Re-exports
export { util } from "./util.js";
export type { UtilOptions } from "./util.js";
</example>
</pattern>
<pattern name="barrel_exports">
<description>index.ts for clean imports</description>
<example>
// src/components/index.ts
export { Button } from "./Button.js";
export { Input } from "./Input.js";
export type { ButtonProps, InputProps } from "./types.js";
</example>
<warning>Can impact tree-shaking; use sparingly</warning>
</pattern>
<pattern name="dynamic_import">
<description>Code splitting with dynamic imports</description>
<example>
const module = await import("./heavy-module.js");
module.doSomething();
</example>
</pattern>
</module_patterns> </runtime_patterns>
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.strictTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
}
);
</example>
<note>import.meta.dirname requires Node.js 20.11+ or 21.2+ (not available in Node.js 18 LTS)</note>
</pattern>
<key_rules>
<rule name="@typescript-eslint/no-explicit-any">Prefer unknown over any</rule>
<rule name="@typescript-eslint/no-unused-vars">Detect unused variables</rule>
<rule name="@typescript-eslint/strict-boolean-expressions">Require explicit boolean conditions</rule>
<rule name="@typescript-eslint/no-floating-promises">Require awaiting promises</rule>
<rule name="@typescript-eslint/prefer-nullish-coalescing">Use ?? over ||</rule>
</key_rules>
export default defineConfig({
test: {
globals: true,
environment: "node",
coverage: {
provider: "v8",
reporter: ["text", "json", "html"],
},
},
});
</example>
</pattern>
</vitest>
<jest>
<pattern name="config">
<description>Jest configuration for TypeScript</description>
<example>
// jest.config.ts
import type { Config } from "jest";
const config: Config = {
preset: "ts-jest",
testEnvironment: "node",
roots: ["<rootDir>/src"],
moduleNameMapper: {
"^@/(.\*)$": "<rootDir>/src/$1",
},
};
export default config;
</example>
</pattern>
</jest>
<build_tools> TypeScript compiler commands <use_case name="compile">tsc - Compile TypeScript</use_case> <use_case name="build">tsc --build - Incremental build (monorepo)</use_case> <use_case name="check">tsc --noEmit - Type check only</use_case> <use_case name="watch">tsc --watch - Watch mode</use_case>
<tsx>
<tool name="tsx">
<description>TypeScript execution with esbuild</description>
<use_case name="run">tsx src/index.ts - Run TypeScript directly</use_case>
<use_case name="watch">tsx watch src/index.ts - Watch mode</use_case>
</tool>
</tsx>
<tsup>
<pattern name="config">
<description>Bundle TypeScript libraries</description>
<example>
// tsup.config.ts
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
format: ["cjs", "esm"],
dts: true,
clean: true,
sourcemap: true,
});
</example>
</pattern>
</tsup>
</build_tools>
<context7_integration> <library_id>/microsoft/typescript</library_id> <trust_score>9.9</trust_score> 16397
<usage_pattern> Resolve library ID if needed (already known: /microsoft/typescript) Fetch documentation with specific topic Configuration options and patterns Generic type patterns Built-in utility types Module resolution strategies </usage_pattern>
<common_queries> Strict compiler options Path aliases configuration Type declaration generation ESM support in Node.js </common_queries> </context7_integration>
<anti_patterns> Overusing 'any' defeats type safety Use 'unknown' and narrow with type guards
type Status = (typeof Status)[keyof typeof Status];
</example>
<best_practices> Enable strict mode in all projects Use noUncheckedIndexedAccess for safer array/object access Prefer 'unknown' over 'any' for unknown types Use 'satisfies' to check types without widening Create branded types for domain primitives Use Result types for error handling over exceptions Keep type definitions close to usage Export types separately with 'export type' Use 'const' assertions for literal types Prefer interfaces for public APIs, types for unions/utilities </best_practices>
<error_escalation> Minor type inference issue Add explicit type annotation Type error in implementation Fix type, verify with tsc Breaking type change in public API Stop, present migration options to user Type safety bypass with any or type assertion Block operation, require proper typing </error_escalation>
<related_skills> Symbol-level navigation for type definitions and interfaces Fetch latest TypeScript compiler and tooling documentation Debug type errors and investigate compilation issues </related_skills>
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
1ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon


