typescript-react-patterns
45
总安装量
45
周安装量
#4684
全站排名
安装命令
npx skills add https://github.com/asyrafhussin/agent-skills --skill typescript-react-patterns
Agent 安装分布
claude-code
32
opencode
30
codex
29
antigravity
24
github-copilot
23
Skill 文档
TypeScript React Patterns
Comprehensive TypeScript patterns for React applications. Contains 35+ rules across 7 categories for building type-safe, maintainable React code.
When to Apply
Reference these guidelines when:
- Typing React component props
- Creating custom hooks with TypeScript
- Handling events with proper types
- Building generic, reusable components
- Fixing TypeScript errors in React code
Rule Categories by Priority
| 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- |
Quick Reference
1. Component Typing (CRITICAL)
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 typing
2. Hook Typing (CRITICAL)
hook-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 hooks
3. Event Handling (HIGH)
event-handler-types– Event handler type patternsevent-synthetic– SyntheticEvent typesevent-form– Form event handlingevent-keyboard– Keyboard event typesevent-mouse– Mouse event typesevent-custom– Custom event types
4. Ref Typing (HIGH)
ref-dom-elements– Refs for DOM elementsref-mutable– Mutable ref patternref-callback– Callback ref typingref-forward– Forwarding refsref-imperative-handle– useImperativeHandle typing
5. Generic Components (MEDIUM)
generic-list– Generic list componentsgeneric-form– Generic form componentsgeneric-select– Generic select/dropdowngeneric-table– Generic table componentsgeneric-constraints– Generic constraints
6. Context & State (MEDIUM)
ctx-create– Creating typed contextctx-provider– Provider typing patternsctx-consumer– useContext with proper typesctx-reducer– Context with reducerctx-default-value– Handling default values
7. Utility Types (LOW)
util-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
Essential Patterns
Component Props
// 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>
)
}
Children Typing
// 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>[]
}
Event Handlers
// 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>
)
}
Refs
// 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 Components
// 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}
/>
Context
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>
)
}
How to Use
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:
- Brief explanation of why it matters
- Incorrect code example with explanation
- Correct code example with explanation
- Additional context and edge cases