typescript
This tool promotes TypeScript best practices by enforcing efficient type inference and avoiding excessive use of the any type.
Install
mkdir -p .claude/skills/typescript && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/579" && unzip -o skill.zip -d .claude/skills/typescript && rm skill.zipInstalls to .claude/skills/typescript
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
LobeHub TypeScript style and type-safety guide. Use when editing TS/TSX/MTS, fixing types, choosing interface vs type, avoiding any/object, import type, async flow, or ts-expect-error.Key capabilities
- →Enforce strictly typed module exports
- →Manage separate type import statements
- →Optimize async/await patterns
- →Implement interface-based type safety
- →Sort import specifiers alphabetically
How it works
It applies a set of strict linting and structural rules to TS code, forcing specific sorting and import styles.
Inputs & outputs
When to use typescript
- →Optimizing TypeScript interface definitions
- →Improving type safety in React/TSX projects
- →Refactoring legacy code to modern TS standards
About this skill
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
-
This project uses
simple-import-sort/importsandconsistent-type-imports(fixStyle: 'separate-type-imports') -
Separate type imports: always use
import type { ... }for type-only imports, NOTimport { type ... }inline syntax -
When a file already has
import type { ... }from a package and you need to add a value import, keep them as two separate statements:import type { ChatTopicBotContext } from '@lobechat/types'; import { RequestTrigger } from '@lobechat/types'; -
Within each import statement, specifiers are sorted alphabetically by name
Code Structure
- Prefer object destructuring
- Use consistent, descriptive naming; avoid obscure abbreviations
- Replace magic numbers/strings with well-named constants
- Defer formatting to tooling
- 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 - Before adding local helpers for common guards/parsing/normalization (record checks, string extraction, empty-string handling, timing helpers, JSON-safe utilities, etc.), search
packages/utilsfirst. If the helper already exists or clearly belongs there, import it from@lobechat/utils(or the relevant@lobechat/utils/*subpath) instead of duplicating tiny helpers across feature files.
UI and Theming
- Use
@lobehub/ui, Ant Design components instead of raw HTML tags - Design for dark mode and mobile responsiveness
- Use
antd-styletoken system instead of hard-coded colors
Performance
- Query only required columns from database
Reusability
- Reuse existing utils in
packages/utilsor installed npm packages - 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
When not to use it
- →JavaScript development (non-TS)
- →Legacy projects requiring namespace pollution
Limitations
- →Can be disruptive if applied to existing legacy codebases
- →Strict import sorting requires developer compliance
How it compares
It imposes a specific stylistic standard for type-only imports and naming that differs from default IDE auto-formats.
Compared to similar skills
typescript side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| typescript (this skill) | 28 | 2mo | No flags | Beginner |
| typescript-skills | 3 | 6mo | Review | Intermediate |
| fullstack-guardian | 1 | 3mo | No flags | Advanced |
| react-patterns | 9 | 6mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by lobehub
View all by lobehub →You might also like
typescript-skills
llama-farm
Shared TypeScript best practices for Designer and Electron subsystems.
fullstack-guardian
Jeffallan
Use when implementing features across frontend and backend, building APIs with UI, or creating end-to-end data flows. Invoke for feature implementation, API development, UI building, cross-stack work.
react-patterns
davila7
Modern React patterns and principles. Hooks, composition, performance, TypeScript best practices.
code-standards
redpanda-data
TypeScript, React, and JavaScript best practices enforced by Ultracite/Biome.
js-tosorted-immutable
TheOrcDev
Use toSorted() instead of sort() to avoid mutating arrays. Apply when sorting arrays that are React props, state, or otherwise shared/referenced elsewhere.
writing-react-effects
dust-tt
Writes React components without unnecessary useEffect. Use when creating/reviewing React components, refactoring effects, or when code uses useEffect to transform data or handle events.