skills/typescript-react-patterns/SKILL.md
TypeScript best practices for React development. Use when writing typed React components, hooks, events, refs, or generic components. Triggers on tasks involving TypeScript errors, type definitions, props typing, or type-safe React patterns.
npx skillsauth add cenjie/skills typescript-react-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Comprehensive TypeScript patterns for React applications. Contains 35+ rules across 7 categories for building type-safe, maintainable React code.
Reference these guidelines when:
| Priority | Category | Impact | Prefix |
|----------|----------|--------|--------|
| 1 | Component Typing | CRITICAL | comp- |
| 2 | Hook Typing | CRITICAL | hook- |
| 3 | Event Handling | HIGH | event- |
| 4 | Ref Typing | HIGH | ref- |
| 5 | Generic Components | MEDIUM | generic- |
| 6 | Context & State | MEDIUM | ctx- |
| 7 | Utility Types | LOW | util- |
comp-props-interface - Use interface for props, type for unionscomp-children-types - Correct children typing patternscomp-default-props - Default props with TypeScriptcomp-forward-ref - Typing forwardRef componentscomp-compound - Compound component patternscomp-polymorphic - "as" prop typinghook-usestate - useState with proper typeshook-useref - useRef for DOM and mutable valueshook-useeffect - useEffect cleanup typinghook-usereducer - useReducer with discriminated unionshook-custom-return - Custom hook return typeshook-generic - Generic custom hooksevent-handler-types - Event handler type patternsevent-synthetic - SyntheticEvent typesevent-form - Form event handlingevent-keyboard - Keyboard event typesevent-mouse - Mouse event typesevent-custom - Custom event typesref-dom-elements - Refs for DOM elementsref-mutable - Mutable ref patternref-callback - Callback ref typingref-forward - Forwarding refsref-imperative-handle - useImperativeHandle typinggeneric-list - Generic list componentsgeneric-form - Generic form componentsgeneric-select - Generic select/dropdowngeneric-table - Generic table componentsgeneric-constraints - Generic constraintsctx-create - Creating typed contextctx-provider - Provider typing patternsctx-consumer - useContext with proper typesctx-reducer - Context with reducerctx-default-value - Handling default valuesutil-react-types - Built-in React typesutil-component-props - ComponentProps utilityutil-pick-omit - Pick and Omit for propsutil-discriminated-unions - State machinesutil-assertion-functions - Type assertions// Use interface for props (extendable)
interface ButtonProps {
variant: 'primary' | 'secondary' | 'danger'
size?: 'sm' | 'md' | 'lg'
isLoading?: boolean
children: React.ReactNode
onClick?: () => void
}
// Use type for unions
type ButtonVariant = 'primary' | 'secondary' | 'danger'
function Button({
variant,
size = 'md',
isLoading = false,
children,
onClick,
}: ButtonProps) {
return (
<button
className={`btn-${variant} btn-${size}`}
onClick={onClick}
disabled={isLoading}
>
{isLoading ? 'Loading...' : children}
</button>
)
}
// ReactNode - most flexible (string, number, element, array, null)
interface CardProps {
children: React.ReactNode
}
// ReactElement - only JSX elements
interface WrapperProps {
children: React.ReactElement
}
// Render prop pattern
interface DataFetcherProps<T> {
children: (data: T) => React.ReactNode
}
// Specific element type
interface TabsProps {
children: React.ReactElement<TabProps> | React.ReactElement<TabProps>[]
}
// Form events
function Form() {
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
// handle submit
}
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
console.log(e.target.value)
}
const handleSelect = (e: React.ChangeEvent<HTMLSelectElement>) => {
console.log(e.target.value)
}
return (
<form onSubmit={handleSubmit}>
<input onChange={handleChange} />
<select onChange={handleSelect}>
<option>A</option>
<option>B</option>
</select>
</form>
)
}
// DOM element ref
function Input() {
const inputRef = useRef<HTMLInputElement>(null)
const focus = () => {
inputRef.current?.focus()
}
return <input ref={inputRef} />
}
// Mutable ref (no null, stores values)
function Timer() {
const intervalRef = useRef<number | undefined>(undefined)
useEffect(() => {
intervalRef.current = window.setInterval(() => {
// tick
}, 1000)
return () => {
clearInterval(intervalRef.current)
}
}, [])
}
// Generic list component
interface ListProps<T> {
items: T[]
renderItem: (item: T, index: number) => React.ReactNode
keyExtractor: (item: T) => string | number
}
function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
return (
<ul>
{items.map((item, index) => (
<li key={keyExtractor(item)}>{renderItem(item, index)}</li>
))}
</ul>
)
}
// Usage - T is inferred
<List
items={users}
renderItem={(user) => <UserCard user={user} />}
keyExtractor={(user) => user.id}
/>
interface AuthContextType {
user: User | null
login: (credentials: Credentials) => Promise<void>
logout: () => void
isLoading: boolean
}
const AuthContext = createContext<AuthContextType | null>(null)
export function useAuth() {
const context = useContext(AuthContext)
if (!context) {
throw new Error('useAuth must be used within AuthProvider')
}
return context
}
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null)
const [isLoading, setIsLoading] = useState(true)
const login = async (credentials: Credentials) => {
// implementation
}
const logout = () => {
setUser(null)
}
return (
<AuthContext.Provider value={{ user, login, logout, isLoading }}>
{children}
</AuthContext.Provider>
)
}
Read individual rule files for detailed explanations and code examples:
rules/comp-props-interface.md
rules/hook-usestate.md
rules/event-handler-types.md
Each rule file contains:
development
Provides React Native performance optimization guidelines for FPS, TTI, bundle size, memory leaks, re-renders, and animations. Applies to tasks involving Hermes optimization, JS thread blocking, bridge overhead, FlashList, native modules, or debugging jank and frame drops.
development
Design engineering principles for making interfaces feel polished. Use when building UI components, reviewing frontend code, implementing animations, hover states, shadows, borders, typography, micro-interactions, enter/exit animations, or any visual detail work. Triggers on UI polish, design details, "make it feel better", "feels off", stagger animations, border radius, optical alignment, font smoothing, tabular numbers, image outlines, box shadows.
development
General-purpose Static Application Security Testing (SAST) skill for code vulnerability analysis. Trigger when the user asks to: "analyze code for vulnerabilities", "review code security", "find security bugs", "do a SAST scan", "check for [vulnerability type] in code", "audit source code", or requests a security code review of any language or framework. Covers 34 vulnerability classes across web, API, auth, mobile, and logic layers.
tools
Helps understand and write EAS workflow YAML files for Expo projects. Use this skill when the user asks about CI/CD or workflows in an Expo or EAS context, mentions .eas/workflows/, or wants help with EAS build pipelines or deployment automation.