typescript-react-patterns
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTypeScript React Patterns
React开发的TypeScript模式
Comprehensive TypeScript patterns for React applications. Contains 35+ rules across 7 categories for building type-safe, maintainable React code.
适用于React应用的全面TypeScript模式集合,包含7个类别下的35+条规则,用于构建类型安全、可维护的React代码。
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
在以下场景中参考这些指南:
- 为React组件Props添加类型标注
- 使用TypeScript创建自定义Hooks
- 为事件处理添加正确的类型
- 构建泛型、可复用组件
- 修复React代码中的TypeScript错误
Rule Categories by Priority
按优先级划分的规则类别
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Component Typing | CRITICAL | |
| 2 | Hook Typing | CRITICAL | |
| 3 | Event Handling | HIGH | |
| 4 | Ref Typing | HIGH | |
| 5 | Generic Components | MEDIUM | |
| 6 | Context & State | MEDIUM | |
| 7 | Utility Types | LOW | |
| 优先级 | 类别 | 影响程度 | 前缀 |
|---|---|---|---|
| 1 | 组件类型标注 | 关键 | |
| 2 | Hook类型标注 | 关键 | |
| 3 | 事件处理 | 高 | |
| 4 | Ref类型标注 | 高 | |
| 5 | 泛型组件 | 中 | |
| 6 | Context与状态 | 中 | |
| 7 | 工具类型 | 低 | |
Quick Reference
快速参考
1. Component Typing (CRITICAL)
1. 组件类型标注(关键)
- - Use interface for props, type for unions
comp-props-interface - - Correct children typing patterns
comp-children-types - - Default props with TypeScript
comp-default-props - - Typing forwardRef components
comp-forward-ref - - Compound component patterns
comp-compound - - "as" prop typing
comp-polymorphic
- - 使用interface定义Props,使用type定义联合类型
comp-props-interface - - 正确的子元素类型标注模式
comp-children-types - - 结合TypeScript使用默认Props
comp-default-props - - 为forwardRef组件添加类型标注
comp-forward-ref - - 复合组件模式
comp-compound - - "as" Props类型标注
comp-polymorphic
2. Hook Typing (CRITICAL)
2. Hook类型标注(关键)
- - useState with proper types
hook-usestate - - useRef for DOM and mutable values
hook-useref - - useEffect cleanup typing
hook-useeffect - - useReducer with discriminated unions
hook-usereducer - - Custom hook return types
hook-custom-return - - Generic custom hooks
hook-generic
- - 为useState添加正确的类型
hook-usestate - - 为DOM元素和可变值使用useRef
hook-useref - - useEffect清理函数的类型标注
hook-useeffect - - 为useReducer区分联合类型
hook-usereducer - - 自定义Hook的返回类型
hook-custom-return - - 泛型自定义Hook
hook-generic
3. Event Handling (HIGH)
3. 事件处理(高)
- - Event handler type patterns
event-handler-types - - SyntheticEvent types
event-synthetic - - Form event handling
event-form - - Keyboard event types
event-keyboard - - Mouse event types
event-mouse - - Custom event types
event-custom
- - 事件处理函数的类型模式
event-handler-types - - SyntheticEvent类型
event-synthetic - - 表单事件处理
event-form - - 键盘事件类型
event-keyboard - - 鼠标事件类型
event-mouse - - 自定义事件类型
event-custom
4. Ref Typing (HIGH)
4. Ref类型标注(高)
- - Refs for DOM elements
ref-dom-elements - - Mutable ref pattern
ref-mutable - - Callback ref typing
ref-callback - - Forwarding refs
ref-forward - - useImperativeHandle typing
ref-imperative-handle
- - DOM元素的Ref
ref-dom-elements - - 可变Ref模式
ref-mutable - - 回调Ref的类型标注
ref-callback - - 转发Ref
ref-forward - - useImperativeHandle的类型标注
ref-imperative-handle
5. Generic Components (MEDIUM)
5. 泛型组件(中)
- - Generic list components
generic-list - - Generic form components
generic-form - - Generic select/dropdown
generic-select - - Generic table components
generic-table - - Generic constraints
generic-constraints
- - 泛型列表组件
generic-list - - 泛型表单组件
generic-form - - 泛型选择器/下拉框
generic-select - - 泛型表格组件
generic-table - - 泛型约束
generic-constraints
6. Context & State (MEDIUM)
6. Context与状态(中)
- - Creating typed context
ctx-create - - Provider typing patterns
ctx-provider - - useContext with proper types
ctx-consumer - - Context with reducer
ctx-reducer - - Handling default values
ctx-default-value
- - 创建带类型的Context
ctx-create - - Provider的类型标注模式
ctx-provider - - 为useContext添加正确的类型
ctx-consumer - - 结合Reducer使用Context
ctx-reducer - - 默认值的处理
ctx-default-value
7. Utility Types (LOW)
7. 工具类型(低)
- - Built-in React types
util-react-types - - ComponentProps utility
util-component-props - - Pick and Omit for props
util-pick-omit - - State machines
util-discriminated-unions - - Type assertions
util-assertion-functions
- - React内置类型
util-react-types - - ComponentProps工具类型
util-component-props - - 用于Props的Pick和Omit
util-pick-omit - - 状态机
util-discriminated-unions - - 类型断言函数
util-assertion-functions
Essential Patterns
核心模式
Component Props
组件Props
typescript
// 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>
)
}typescript
// 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
子元素类型标注
typescript
// 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>[]
}typescript
// 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
事件处理函数
typescript
// 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>
)
}typescript
// 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
Refs
typescript
// 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)
}
}, [])
}typescript
// 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
泛型组件
typescript
// 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}
/>typescript
// 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
Context
typescript
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>
)
}typescript
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.mdEach rule file contains:
- Brief explanation of why it matters
- Incorrect code example with explanation
- Correct code example with explanation
- Additional context and edge cases
阅读单个规则文件获取详细说明和代码示例:
rules/comp-props-interface.md
rules/hook-usestate.md
rules/event-handler-types.md每个规则文件包含:
- 规则重要性的简要说明
- 错误代码示例及解释
- 正确代码示例及解释
- 额外背景信息和边缘情况说明