0Pricing
TypeScript Academy · 课时

为 useState 和 useReducer 添加类型

为 React 状态钩子添加类型参数

为 useState 和 useReducer 添加类型 是 CoddyKit 上的免费 TypeScript Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 TypeScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 TypeScript Academy 课程共包含 4 节课。

欢迎

本课将介绍如何在使用 React 时,使用 TypeScript 为 useState 和 useReducer 添加类型。

组件属性接口

为 React 组件定义属性接口,以记录并强制约束组件 API。
interface ButtonProps {
  label: string;
  onClick: () => void;
  disabled?: boolean;
}

function Button({ label, onClick, disabled }: ButtonProps) {
  return <button onClick={onClick} disabled={disabled}>{label}</button>;
}

FC 与显式返回类型

React.FC 会自动添加 children 和其他类型。显式返回类型(JSX.Element | null)通常更加清晰。
const Card: React.FC<{title: string}> = ({ title }) => <div>{title}</div>;

// Or explicit:
function Card2({ title }: { title: string }): JSX.Element {
  return <div>{title}</div>;
}

useState 类型标注

useState 会根据初始值推断类型。当初始值为 null 或存在歧义时,请提供类型参数。
const [count, setCount] = useState(0);           // number
const [name, setName] = useState('');            // string
const [user, setUser] = useState<User | null>(null); // explicit

useReducer 类型标注

将 useReducer 与可辨识联合操作类型结合使用效果最佳。
type Action = { type: 'increment' } | { type: 'decrement' } | { type: 'reset'; value: number };
function reducer(state: number, action: Action): number {
  switch (action.type) {
    case 'increment': return state + 1;
    case 'decrement': return state - 1;
    case 'reset': return action.value;
  }
}

为 DOM 添加 useRef 类型

用于 DOM 元素的 useRef 需要类型参数。由于元素尚不存在,请使用 null 初始化。
const inputRef = useRef<HTMLInputElement>(null);

// Use:
if (inputRef.current) {
  inputRef.current.focus();
}

事件处理程序类型标注

React 事件类型包括 React.ChangeEvent、React.MouseEvent 和 React.FormEvent。
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
  console.log(e.target.value);
}
function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
  e.preventDefault();
}

泛型组件

泛型组件接受类型参数,可用于构建灵活且类型安全的列表和选择控件。
function List<T extends { id: number }>({ items }: { items: T[] }) {
  return <ul>{items.map(i => <li key={i.id}>{JSON.stringify(i)}</li>)}</ul>;
}

使用 TypeScript 的 forwardRef

forwardRef 需要分别为 ref 元素类型和属性指定类型参数。
const Input = React.forwardRef<HTMLInputElement, InputProps>(
  ({ label, ...props }, ref) => (
    <label>{label}<input {...props} ref={ref} /></label>
  )
);

自定义钩子返回类型

请显式标注自定义钩子的返回值类型,以避免元组返回值被推断为 any[]。
function useToggle(init: boolean): [boolean, () => void] {
  const [state, setState] = useState(init);
  return [state, () => setState(s => !s)];
}

使用 TypeScript 的上下文

为 React 上下文指定一个包含 undefined 的联合类型,强制使用者检查上下文是否存在。
const AuthContext = React.createContext<User | undefined>(undefined);
function useAuth(): User {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be used within AuthProvider');
  return ctx;
}

快速检查

指向 HTML input 元素的 ref 的正确类型是什么?

回顾

使用接口为 React 属性添加类型,使用类型参数为 useState 添加类型,使用 React 事件类型为事件添加类型,使用 DOM 元素泛型为 ref 添加类型,并使用双类型参数为 forwardRef 添加类型。泛型组件可以实现类型安全且可复用的用户界面。

常见问题解答

「为 useState 和 useReducer 添加类型」课时是免费的吗?

是的 — 「为 useState 和 useReducer 添加类型」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 TypeScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 TypeScript Academy 课程共包含 4 节课。

「为 useState 和 useReducer 添加类型」这节课中我会学到什么?

为 React 状态钩子添加类型参数 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 TypeScript Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 TypeScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「为 useState 和 useReducer 添加类型」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 TypeScript Academy 课中编写并运行代码吗?

能。每节 TypeScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 为 React 组件属性添加类型
  2. 为 useState 和 useReducer 添加类型
  3. 为 useRef 与事件处理器添加类型
  4. 泛型组件与 forwardRef
← 返回 TypeScript Academy