typescript-react-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TypeScript 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

按优先级划分的规则类别

PriorityCategoryImpactPrefix
1Component TypingCRITICAL
comp-
2Hook TypingCRITICAL
hook-
3Event HandlingHIGH
event-
4Ref TypingHIGH
ref-
5Generic ComponentsMEDIUM
generic-
6Context & StateMEDIUM
ctx-
7Utility TypesLOW
util-
优先级类别影响程度前缀
1组件类型标注关键
comp-
2Hook类型标注关键
hook-
3事件处理
event-
4Ref类型标注
ref-
5泛型组件
generic-
6Context与状态
ctx-
7工具类型
util-

Quick Reference

快速参考

1. Component Typing (CRITICAL)

1. 组件类型标注(关键)

  • comp-props-interface
    - Use interface for props, type for unions
  • comp-children-types
    - Correct children typing patterns
  • comp-default-props
    - Default props with TypeScript
  • comp-forward-ref
    - Typing forwardRef components
  • comp-compound
    - Compound component patterns
  • comp-polymorphic
    - "as" prop typing
  • comp-props-interface
    - 使用interface定义Props,使用type定义联合类型
  • comp-children-types
    - 正确的子元素类型标注模式
  • comp-default-props
    - 结合TypeScript使用默认Props
  • comp-forward-ref
    - 为forwardRef组件添加类型标注
  • comp-compound
    - 复合组件模式
  • comp-polymorphic
    - "as" Props类型标注

2. Hook Typing (CRITICAL)

2. Hook类型标注(关键)

  • hook-usestate
    - useState with proper types
  • hook-useref
    - useRef for DOM and mutable values
  • hook-useeffect
    - useEffect cleanup typing
  • hook-usereducer
    - useReducer with discriminated unions
  • hook-custom-return
    - Custom hook return types
  • hook-generic
    - Generic custom hooks
  • hook-usestate
    - 为useState添加正确的类型
  • hook-useref
    - 为DOM元素和可变值使用useRef
  • hook-useeffect
    - useEffect清理函数的类型标注
  • hook-usereducer
    - 为useReducer区分联合类型
  • hook-custom-return
    - 自定义Hook的返回类型
  • hook-generic
    - 泛型自定义Hook

3. Event Handling (HIGH)

3. 事件处理(高)

  • event-handler-types
    - Event handler type patterns
  • event-synthetic
    - SyntheticEvent types
  • event-form
    - Form event handling
  • event-keyboard
    - Keyboard event types
  • event-mouse
    - Mouse event types
  • event-custom
    - Custom event types
  • event-handler-types
    - 事件处理函数的类型模式
  • event-synthetic
    - SyntheticEvent类型
  • event-form
    - 表单事件处理
  • event-keyboard
    - 键盘事件类型
  • event-mouse
    - 鼠标事件类型
  • event-custom
    - 自定义事件类型

4. Ref Typing (HIGH)

4. Ref类型标注(高)

  • ref-dom-elements
    - Refs for DOM elements
  • ref-mutable
    - Mutable ref pattern
  • ref-callback
    - Callback ref typing
  • ref-forward
    - Forwarding refs
  • ref-imperative-handle
    - useImperativeHandle typing
  • ref-dom-elements
    - DOM元素的Ref
  • ref-mutable
    - 可变Ref模式
  • ref-callback
    - 回调Ref的类型标注
  • ref-forward
    - 转发Ref
  • ref-imperative-handle
    - useImperativeHandle的类型标注

5. Generic Components (MEDIUM)

5. 泛型组件(中)

  • generic-list
    - Generic list components
  • generic-form
    - Generic form components
  • generic-select
    - Generic select/dropdown
  • generic-table
    - Generic table components
  • generic-constraints
    - Generic constraints
  • generic-list
    - 泛型列表组件
  • generic-form
    - 泛型表单组件
  • generic-select
    - 泛型选择器/下拉框
  • generic-table
    - 泛型表格组件
  • generic-constraints
    - 泛型约束

6. Context & State (MEDIUM)

6. Context与状态(中)

  • ctx-create
    - Creating typed context
  • ctx-provider
    - Provider typing patterns
  • ctx-consumer
    - useContext with proper types
  • ctx-reducer
    - Context with reducer
  • ctx-default-value
    - Handling default values
  • ctx-create
    - 创建带类型的Context
  • ctx-provider
    - Provider的类型标注模式
  • ctx-consumer
    - 为useContext添加正确的类型
  • ctx-reducer
    - 结合Reducer使用Context
  • ctx-default-value
    - 默认值的处理

7. Utility Types (LOW)

7. 工具类型(低)

  • util-react-types
    - Built-in React types
  • util-component-props
    - ComponentProps utility
  • util-pick-omit
    - Pick and Omit for props
  • util-discriminated-unions
    - State machines
  • util-assertion-functions
    - Type assertions
  • util-react-types
    - React内置类型
  • util-component-props
    - ComponentProps工具类型
  • util-pick-omit
    - 用于Props的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.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
阅读单个规则文件获取详细说明和代码示例:
rules/comp-props-interface.md
rules/hook-usestate.md
rules/event-handler-types.md
每个规则文件包含:
  • 规则重要性的简要说明
  • 错误代码示例及解释
  • 正确代码示例及解释
  • 额外背景信息和边缘情况说明