目录
[1. 内置类型声明](#1. 内置类型声明)
[2. 第三方库类型声明](#2. 第三方库类型声明)
[1. 项目内共享类型](#1. 项目内共享类型)
[2. 为已有 JS 文件提供类型声明](#2. 为已有 JS 文件提供类型声明)
[3. 使用 declare 声明全局变量](#3. 使用 declare 声明全局变量)
[四、在 React 中使用 TypeScript](#四、在 React 中使用 TypeScript)
[1. 创建支持 TypeScript 的 React 项目](#1. 创建支持 TypeScript 的 React 项目)
[2. 函数组件(Function Component)](#2. 函数组件(Function Component))
[3. 事件处理](#3. 事件处理)
[4. Class 组件](#4. Class 组件)
[5. React Hooks 类型](#5. React Hooks 类型)
[6. 自定义 Hooks 类型](#6. 自定义 Hooks 类型)
[7. 高阶组件(HOC)类型](#7. 高阶组件(HOC)类型)
[五、TypeScript 配置文件 tsconfig.json 常用配置](#五、TypeScript 配置文件 tsconfig.json 常用配置)
本文介绍了TypeScript中的类型声明文件(.d.ts)及其应用场景,包括为JavaScript库提供类型支持、使用内置和第三方类型声明。
重点讲解了在React项目中使用TypeScript的方法,包括函数组件、事件处理、Class组件和React Hooks的类型定义,以及自定义Hooks和高阶组件的类型处理。最后介绍了TypeScript配置文件tsconfig.json的常用配置选项。通过类型声明文件,开发者可以在项目中获得更好的类型提示和检查,提高代码质量和开发效率。
一、类型声明文件(.d.ts)
TypeScript 有两种文件类型:
-
.ts:包含类型和实现,编译后生成.js -
.d.ts:仅包含类型声明,不会生成 JS,用于提供类型信息
作用:为已有 JavaScript 库提供类型支持,让 TypeScript 项目能够使用这些库并获得类型提示。
二、使用已有的类型声明文件
1. 内置类型声明
TypeScript 自带了 DOM、BOM、ES 内置 API 的类型声明,如 lib.es5.d.ts、lib.dom.d.ts。
2. 第三方库类型声明
-
自带类型 :有些库(如 axios)在 npm 包中包含了
.d.ts文件。 -
DefinitelyTyped :对于没有自带类型的库,可以安装
@types/库名获取类型。
bash
npm install @types/react @types/react-dom
三、创建自己的类型声明文件
1. 项目内共享类型
创建 types.d.ts:
TypeScript
export interface User {
id: number;
name: string;
}
在 .ts 文件中导入:
TypeScript
import { User } from "./types";
2. 为已有 JS 文件提供类型声明
假设有一个 utils.js:
javascript
export function add(a, b) {
return a + b;
}
创建 utils.d.ts:
TypeScript
export declare function add(a: number, b: number): number;
3. 使用 declare 声明全局变量
TypeScript
// global.d.ts
declare const MY_GLOBAL: string;
四、在 React 中使用 TypeScript
前提说明:现在,基于 class 组件来讲解 React+TS 的使用(最新的 React Hooks,在后面讲解)。
在不使用 TS 时,可以使用 prop-types 库,为 React 组件提供类型检查 https://legacy.reactjs.org/docs/typechecking-with-proptypes.html 。
说明: TS 项目中,推荐使用 TypeScript 实现组件类型校验(代替 PropTypes) 。
不管是 React 还是 Vue,只要是支持 TS 的库,都提供了很多类型,来满足该库对类型的需求。
注意:
- React 项目是通过 @types/react、@types/react-dom 类型声明包,来提供类型的。
- 这些包 CRA 已帮我们安装好(react-app-env.d.ts),直接用即可。
参考资料:
https://legacy.reactjs.org/docs/static-type-checking.html 、 https://github.com/typescript-cheatsheets/react 。
1. 创建支持 TypeScript 的 React 项目
TypeScript
-- 创建react支持Typescript
npm create vite@latest my-app -- --template react-ts
-- 创建react默认使用并支持JavaScript
# 使用 npm
npm create vite@latest my-react-app -- --template react
# 或使用 yarn
yarn create vite my-react-app --template react
# 或使用 pnpm
pnpm create vite my-react-app --template react
主要变化:
-
tsconfig.json:TS 编译配置 -
*.tsx:包含 JSX 的组件文件 -
react-app-env.d.ts:默认类型声明文件
2. 函数组件(Function Component)
TypeScript
type Props = {
name: string;
age?: number;
};
const Hello: React.FC<Props> = ({ name, age = 18 }) => {
return <div>你好,{name},你 {age} 岁</div>;
};
// 或者更简洁的写法
const Hello = ({ name, age = 18 }: Props) => {
return <div>你好,{name},你 {age} 岁</div>;
};
3. 事件处理
TypeScript
// 按钮点击
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
console.log(e.currentTarget);
};
// 输入框变化
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
console.log(e.target.value);
};
// 表单提交
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
};
4. Class 组件
TypeScript
type Props = { name: string };
type State = { count: number };
class Counter extends React.Component<Props, State> {
state: State = { count: 0 };
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
{this.props.name}: {this.state.count}
<button onClick={this.increment}>+1</button>
</div>
);
}
}
5. React Hooks 类型
- useState
TypeScript
const [count, setCount] = useState<number>(0);
// 或者依靠类型推断
const [count, setCount] = useState(0); // count 类型为 number
- useReducer
TypeScript
type State = { count: number };
type Action = { type: "increment" } | { type: "decrement" };
const reducer = (state: State, action: Action): State => {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
return state;
}
};
const [state, dispatch] = useReducer(reducer, { count: 0 });
- useRef
TypeScript
// 用于 DOM 元素
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
// 用于存储可变值
const intervalRef = useRef<number | null>(null);
- useContext
TypeScript
type Theme = "light" | "dark";
const ThemeContext = createContext<Theme>("light");
const Child = () => {
const theme = useContext(ThemeContext);
return <div>Current theme: {theme}</div>;
};
- useMemo / useCallback
TypeScript
const expensiveValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
const handleClick = useCallback(() => {
console.log("clicked");
}, []);
6. 自定义 Hooks 类型
TypeScript
function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T) => void] {
const [storedValue, setStoredValue] = useState<T>(() => {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
});
const setValue = (value: T) => {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
};
return [storedValue, setValue];
}
7. 高阶组件(HOC)类型
TypeScript
const withAuth = <P extends object>(Component: React.ComponentType<P>) => {
return (props: P) => {
const isLoggedIn = true;
if (!isLoggedIn) return <div>请登录</div>;
return <Component {...props} />;
};
};
五、TypeScript 配置文件 tsconfig.json 常用配置
TypeScript
{
"compilerOptions": {
"target": "es5", // 编译目标
"lib": ["dom", "es2015"], // 包含的类型库
"jsx": "react", // JSX 编译方式
"strict": true, // 启用所有严格类型检查
"esModuleInterop": true, // 支持 CommonJS 和 ES 模块互操作
"skipLibCheck": true, // 跳过库文件类型检查
"forceConsistentCasingInFileNames": true
},
"include": ["src"]
}