Components
import React from 'react'
// Written as a function declaration
function Heading(): React.ReactNode {
return <h1>My Website Heading</h1>
}
// Written as a function expression
const OtherHeading: React.FC = () => <h1>My Website Heading</h1>
Props
import React from 'react';
interface Props {
name: string;
color: string;
}
type OtherProps = {
name: string;
color: string;
}
// Notice here we're using the functiion declaration with the interface Props
function Heading({ name, color }: Props): React.ReactNode {
return <h1>My Website Heading</h1>
}
// Notice here we're using the function expression with the type OtherProps
const OtherHeading: React.FC<OtherProps> = ({ name, color }) => {
return <h1>My Website Heading</h1>
}
当涉及到 type 或 interface 时,我们建议遵循 react-typescript-cheatsheet 社区提出的指南:
- 在编写库或第 3 方环境类型定义时,始终使用 interface 作为公共 API 的定义
- 考虑在 React 组件 Props 和 State 使用 type,因为它更受限制。
| Aspect | Type | Interface |
|---|---|---|
| Can describe functions | ✅ | ✅ |
| Can describe constructors | ✅ | ✅ |
| Can describe tuples | ✅ | ✅ |
| Interfaces can extend it | ⚠️ | ✅ |
| Classes can extend it | 🚫 | ✅ |
Classes can implement it (implements) | ⚠️ | ✅ |
| Can intersect another one of its kind | ✅ | ⚠️ |
| Can create a union with another one of its kind | ✅ | 🚫 |
| Can be used to create mapped types | ✅ | 🚫 |
| Can be mapped over with mapped types | ✅ | ✅ |
| Expands in error messages and logs | ✅ | 🚫 |
| Can be augmented | 🚫 | ✅ |
| Can be recursive | ⚠️ | ✅ |
Extending Component Props
type
import React from 'react';
type ButtonProps = {
/** the background color of the button */
color: string;
/** the text to show inside the button */
text: string;
}
type ContainerProps = ButtonProps & {
/** the height of the container (value used with 'px') */
height: number;
}
const Container: React.FC<ContainerProps> = ({ color, text, height}) => {
return <div style={{ backgroundColor: color, height: `${height}px` }}>{text}</div>
}
interface
import React from 'react';
interface ButtonProps {
/** the background color of the button */
color: string;
/** the text to show inside the button */
text: string;
}
interface ContainerProps extends ButtonProps {
/** the height of the container (value used with 'px') */
height: number;
}
const Container: React.FC<ContainerProps> = ({ color, height, width, text }) => {
return <div style={{ backgroundColor: color, height: `${height}px` }}>{text}</div>
}
Handling Form Events
import React, { useState } from 'react';
const MyInput = () => {
const [value, setValue] = useState('');
function onChange(e: React.ChangeEvent<HTMLInputElement>) {
setVaue(e.target.value)
}
return <input value={value} onChange={onChange} id="input-example"/>
}
Third-party Libraries
#yarn
yarn add @types/<package-name>
#npm
npm install @types/<package-name>
-
Should these be saved as
dependenciesordevDependenciesin mypackage.json?简短的回答是“视情况而定”。大多数情况下,如果您正在构建 Web 应用程序,它们可以归入 devDependencies。但是,如果您正在使用 TypeScript 编写 React 库,您可能希望将它们作为依赖项包含在内。
-
What happens if they don’t have a @types package?
two options:
- Add a basic declaration file
- Add a thorough declaration file
参考文档
React with TypeScript: Best Practices
推荐阅读