Use for TypeScript style and type safety when editing TS/TSX/MTS, including imports, async code and error suppression.
Install
npx skills add https://github.com/lobehub/lobehub --skill typescriptSKILL.md
TypeScript Code Style Guide
Types and Type Safety
- Avoid explicit type annotations when TypeScript can infer
- Avoid implicitly
any; explicitly type when necessary - Use accurate types: prefer
Record<PropertyKey, unknown>overobjectorany - Prefer
interfacefor object shapes (e.g., React props); usetypefor unions/intersections - Prefer
as const satisfies XyzInterfaceover plainas const - Prefer
@ts-expect-errorover@ts-ignoreoveras any - Avoid meaningless null/undefined parameters; design strict function contracts
- Prefer ES module augmentation (
declare module '...') overnamespace; do not introducenamespace-based extension patterns - When a type needs extensibility, expose a small mergeable interface at the source type and let each feature/plugin augment it locally instead of centralizing all extension fields in one registry file
- For package-local extensibility patterns like
PipelineContext.metadata, define the metadata fields next to the processor/provider/plugin that reads or writes them
Async Patterns
- Prefer
async/awaitover callbacks or.then()chains - Async-first for IO: new IO code (fs, child_process, etc.) must use async APIs at its boundaries — use promise-based variants like
import { readFile } from 'fs/promises', never*Syncby default. Function coloring is asymmetric: async→sync migration is never needed, while sync→async (when IO gets slower, gains concurrency, or grows a subprocess/network call) forces rewriting every caller up the chain — sync-first debt that compounds. Micro-costs of async (thread-pool dispatch, cache races) are not valid reasons: races are solved by caching the promise instead of the result *Syncis acceptable in exactly one place: call sites locked inside a synchronous contract you don't control — an existing sync signature chain (don't virally refactor a legacy sync chain in a bugfix, but new standalone modules must not extend such chains), or sync-only callbacks likeprocess.on('exit'). Module-load-time and CLI startup init are NOT exceptions — use top-levelawait(ESM) there- Use
Promise.all,Promise.racefor concurrent operations where safe
Imports
- Let lint enforce
simple-import-sort/importsandconsistent-type-importswith separateimport typestatements (fixStyle: 'separate-type-imports').
Code Structure
- Prefer named exports over
export default— keeps refactor renames and IDE auto-import in sync, and avoids thedefaultre-naming drift you get withimport Foo from './foo'. Reserveexport defaultfor files where the framework requires it (Next.js page/route/layout, React.lazy targets, config files likevitest.config.ts). The codebase still has manyexport defaultoccurrences — that's historical debt, not a pattern to copy; do not model new code on existingexport defaultusage outside the framework-required cases above
Reusability
- Before adding guards, parsing, normalization, timing, or JSON-safe helpers, search
packages/utilsand installed packages. Reuse@lobechat/utilsor its relevant subpath instead of duplicating helpers across features. - Do not hand-roll reusable record/object-map guards such as
typeof value === 'object' && value !== null; import helpers likeisRecord,isPlainRecord,isObjectLike,toRecord,pickString,UnknownRecord, etc. from@lobechat/utils/object. - Assign
Date.now()to a constant once and reuse for consistency
Logging
- Never log user private information (API keys, etc.)
- Don't use
import { log } from 'debug'directly (logs to console) - Use
console.errorin catch blocks instead of debug package - Always log the error in
.catch()callbacks — silent.catch(() => fallback)swallows failures and makes debugging impossible
Related skills
typescript-advanced-typeswshobson81KMaster TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects.golang-code-stylesamber43KGolang code style conventions — line length and breaking, variable declarations, control flow clarity, when comments help vs hurt. Use when writing or reviewing Go code, asking about style or clarity, or establishing project coding standards. Not for naming conventions (→ See `samber/cc-skills-golang@golang-naming` skill), linter configuration (→ See `samber/cc-skills-golang@golang-lint` skill), or doc comments (→ See `samber/cc-skills-golang@golang-documentation` skill).golang-error-handlingsamber42KIdiomatic Golang error handling — creation, wrapping with %w, errors.Is/As, errors.Join, custom error types, sentinel errors, panic/recover, the single handling rule, structured logging with slog, HTTP request logging middleware, and samber/oops for production errors. Built to make logs usable at scale with log aggregation 3rd-party tools. Apply when creating, wrapping, inspecting, or logging errors in Go code. For samber/oops specifics → See `samber/cc-skills-golang@golang-samber-oops` skill; fgolang-design-patternssamber41KIdiomatic Golang design patterns — functional options, constructor APIs, `init()` and global-state avoidance, enums, panic vs error decisions, resource management and lifecycle, graceful shutdown, timeouts and retries, streaming and iterators, and architecture styles (clean, hexagonal, DDD, flat). Apply when choosing between architectural patterns, implementing functional options, designing constructor APIs, setting up graceful shutdown, applying resilience patterns, or asking which idiomatic Go