TypeScript + React 实战入门(组件 + Hooks + Props)

本文将通过真实 React 组件示例,系统讲解如何在 React 中正确使用 TypeScript, 重点放在组件 Props、Hooks 类型、工程实践方式,而不是零散语法。


一、为什么 React 项目一定要配 TypeScript?

在 React 项目中,以下问题极为常见:

  • Props 传错字段,但运行时才发现
  • 组件被错误使用,却没有任何提示
  • 重构组件时,不知道哪些地方会受影响

TypeScript 在 React 中的核心价值:

  • Props 变成可校验的契约
  • 组件使用方式一目了然
  • Hooks 返回值类型清晰
  • 重构时 IDE 自动兜底

二、准备工作:创建 TypeScript React 项目

方式一:使用 Vite(推荐)


npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev

目录结构示例


src/
├── components/
│   └── Header.tsx
├── App.tsx
├── main.tsx

注意:React + TS 中,组件文件使用 .tsx 后缀。


三、第一个 TypeScript React 组件

1. 最简单的函数组件


function Hello() {
  return "Hello TypeScript + React";
}

export default Hello;

此时没有任何类型,但 TypeScript 已能推断 JSX 返回值。


四、Props 的正确类型定义方式(重点)

1. 用 interface 定义 Props


interface HeaderProps {
  title: string;
  subtitle?: string;
}

2. 在组件中使用 Props


function Header(props: HeaderProps) {
  const { title, subtitle } = props;

  return (
    <header>
      <h1>{title}</h1>
      {subtitle && <p>{subtitle}</p>}
    </header>
  );
}

export default Header;

3. 使用组件(IDE 会自动提示)


<Header title="首页" subtitle="欢迎使用 TypeScript" />

收益:

  • 漏传 title 会直接报错
  • 传多余字段会提示不合法
  • 组件即文档

五、React.FC 要不要用?

不推荐写法


const Header: React.FC<HeaderProps> = ({ title }) => {
  return <h1>{title}</h1>;
};

推荐写法


function Header({ title }: HeaderProps) {
  return <h1>{title}</h1>;
}

原因:

  • React.FC 会隐式带上 children
  • 对初学者不友好
  • 社区已逐步不推荐

六、useState 的 TypeScript 用法

1. 自动类型推断(最常见)


const [count, setCount] = useState(0);

TypeScript 会自动推断 countnumber

2. 显式声明类型(复杂状态)


interface User {
  id: number;
  name: string;
}

const [user, setUser] = useState<User | null>(null);

七、useEffect 的类型认知


useEffect(() => {
  console.log("组件挂载");
}, []);

注意:

  • useEffect 回调不能直接声明为 async
  • 返回值只能是清理函数或 void

八、事件处理的类型写法

1. 输入框 change 事件


function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
  console.log(e.target.value);
}

2. 按钮点击事件


function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
  console.log("clicked");
}

九、一个完整的 TS + React 示例


import { useState } from "react";

interface CounterProps {
  initialValue?: number;
}

function Counter({ initialValue = 0 }: CounterProps) {
  const [count, setCount] = useState(initialValue);

  return (
    <div>
      <p>当前值:{count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

export default Counter;

这个组件同时体现了:

  • Props 类型定义
  • useState 类型推断
  • 默认 Props

十、React + TypeScript 常见误区

  • 为了省事使用 any
  • Props 不抽接口,直接内联写类型
  • useState 初始值写错导致类型混乱
  • 关闭 strict 模式“先跑起来”

十一、实践建议(非常重要)

  • 组件先设计 Props,再写 JSX
  • 状态复杂时,一定定义接口
  • 让 TypeScript 报错,而不是绕过它
  • 把组件当成“有类型的函数”

结语

TypeScript + React 的真正威力,在于“约束协作”。
当组件数量增加、参与者变多时,类型系统会成为最可靠的工程保障。

一旦你习惯了这种方式,就很难再回到“无类型 React”。

发表评论