TypeScript与React #

一、React组件类型 #

1.1 函数组件 #

typescript
import React from 'react';

interface ButtonProps {
    text: string;
    onClick: () => void;
}

const Button: React.FC<ButtonProps> = ({ text, onClick }) => {
    return <button onClick={onClick}>{text}</button>;
};

const Button = ({ text, onClick }: ButtonProps) => {
    return <button onClick={onClick}>{text}</button>;
};

1.2 类组件 #

typescript
import React from 'react';

interface CounterProps {
    initialValue?: number;
}

interface CounterState {
    count: number;
}

class Counter extends React.Component<CounterProps, CounterState> {
    state: CounterState = {
        count: this.props.initialValue ?? 0
    };
    
    increment = () => {
        this.setState({ count: this.state.count + 1 });
    };
    
    render() {
        return (
            <div>
                <span>{this.state.count}</span>
                <button onClick={this.increment}>+</button>
            </div>
        );
    }
}

二、Props类型 #

2.1 基本Props #

typescript
interface UserCardProps {
    name: string;
    age: number;
    email?: string;
    onClick?: () => void;
}

const UserCard = ({ name, age, email, onClick }: UserCardProps) => {
    return (
        <div onClick={onClick}>
            <h2>{name}</h2>
            <p>Age: {age}</p>
            {email && <p>Email: {email}</p>}
        </div>
    );
};

2.2 子元素类型 #

typescript
interface ContainerProps {
    children: React.ReactNode;
}

const Container = ({ children }: ContainerProps) => {
    return <div className="container">{children}</div>;
};

interface LayoutProps {
    header: React.ReactNode;
    children: React.ReactNode;
    footer?: React.ReactNode;
}

const Layout = ({ header, children, footer }: LayoutProps) => {
    return (
        <div>
            <header>{header}</header>
            <main>{children}</main>
            {footer && <footer>{footer}</footer>}
        </div>
    );
};

2.3 事件处理类型 #

typescript
interface FormProps {
    onSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
    onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
    onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
}

const Form = ({ onSubmit, onChange, onClick }: FormProps) => {
    return (
        <form onSubmit={onSubmit}>
            <input onChange={onChange} />
            <button onClick={onClick}>Submit</button>
        </form>
    );
};

2.4 样式类型 #

typescript
interface StyledButtonProps {
    style?: React.CSSProperties;
    className?: string;
}

const StyledButton = ({ style, className }: StyledButtonProps) => {
    return (
        <button style={style} className={className}>
            Click me
        </button>
    );
};

三、Hooks类型 #

3.1 useState #

typescript
const [count, setCount] = useState<number>(0);

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

const [items, setItems] = useState<string[]>([]);

3.2 useEffect #

typescript
useEffect(() => {
    console.log('Component mounted');
    
    return () => {
        console.log('Component unmounted');
    };
}, []);

useEffect(() => {
    console.log('Count changed:', count);
}, [count]);

3.3 useRef #

typescript
const inputRef = useRef<HTMLInputElement>(null);

const focusInput = () => {
    inputRef.current?.focus();
};

return <input ref={inputRef} />;

3.4 useContext #

typescript
interface ThemeContextType {
    theme: 'light' | 'dark';
    toggleTheme: () => void;
}

const ThemeContext = createContext<ThemeContextType | undefined>(undefined);

const useTheme = () => {
    const context = useContext(ThemeContext);
    if (!context) {
        throw new Error('useTheme must be used within ThemeProvider');
    }
    return context;
};

3.5 useReducer #

typescript
type State = {
    count: number;
};

type Action = 
    | { type: 'increment' }
    | { type: 'decrement' }
    | { type: 'reset'; payload: number };

const reducer = (state: State, action: Action): State => {
    switch (action.type) {
        case 'increment':
            return { count: state.count + 1 };
        case 'decrement':
            return { count: state.count - 1 };
        case 'reset':
            return { count: action.payload };
    }
};

const [state, dispatch] = useReducer(reducer, { count: 0 });

3.6 自定义Hook #

typescript
function useFetch<T>(url: string): {
    data: T | null;
    loading: boolean;
    error: Error | null;
} {
    const [data, setData] = useState<T | null>(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<Error | null>(null);
    
    useEffect(() => {
        fetch(url)
            .then(res => res.json())
            .then(setData)
            .catch(setError)
            .finally(() => setLoading(false));
    }, [url]);
    
    return { data, loading, error };
}

四、事件处理 #

4.1 事件类型 #

typescript
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    console.log(event.currentTarget.value);
};

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    console.log(event.target.value);
};

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
};

4.2 泛型事件处理 #

typescript
function handleEvent<T extends HTMLElement>(
    event: React.MouseEvent<T>
): void {
    console.log(event.currentTarget);
}

五、实用示例 #

5.1 API组件 #

typescript
interface UserListProps {
    users: User[];
    onSelect: (user: User) => void;
}

const UserList = ({ users, onSelect }: UserListProps) => {
    return (
        <ul>
            {users.map(user => (
                <li key={user.id} onClick={() => onSelect(user)}>
                    {user.name}
                </li>
            ))}
        </ul>
    );
};

5.2 表单组件 #

typescript
interface FormData {
    username: string;
    password: string;
}

const LoginForm = () => {
    const [formData, setFormData] = useState<FormData>({
        username: '',
        password: ''
    });
    
    const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const { name, value } = e.target;
        setFormData(prev => ({ ...prev, [name]: value }));
    };
    
    const handleSubmit = (e: React.FormEvent) => {
        e.preventDefault();
        console.log(formData);
    };
    
    return (
        <form onSubmit={handleSubmit}>
            <input name="username" onChange={handleChange} />
            <input name="password" type="password" onChange={handleChange} />
            <button type="submit">Login</button>
        </form>
    );
};

六、总结 #

本章介绍了TypeScript与React的结合:

组件类型 #

  1. 函数组件
  2. 类组件
  3. Props类型

Hooks类型 #

  1. useState
  2. useEffect
  3. useRef
  4. useContext
  5. useReducer

最佳实践 #

  1. 显式定义Props类型
  2. 使用类型安全的Hooks
  3. 正确处理事件类型
最后更新:2026-03-26