为了使系统方便维护,我们会在项目中引入 Typescript,通过使用 TypeScript,可以更好地定义对象和函数的类型,减少错误,提高代码的可读性和可维护性。然而大部分新手刚接触 Typescript 或者 React ,不知道如何声明Props,类组件,函数组件等。接下来让我们通过例子来走进 React 和 Typescript 世界。
常见的Props类型声明
下面是常见的类型声明,我们通过
type
关键字来声明,当然你也可以通过
interface
来声明。
type Props = {
name: string;
age: number;
disabled: boolean;
students: Array<{
name: string;
age: number;
}>;
people: {
name: string;
age: number;
obj2: object;
obj3: {};
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
onSubmit: (val: string) => void;
optional?: string;
}
在 TypeScript 中,object 作为非原始类型,可能会引起误解。实际上,object 并不是指“任何对象”,而是指“任何非原始类型”。也就是说,object 表示的并不是数字、字符串、布尔值、符号、null 或 undefined。通常在声明对象时,我们不会用 object,而是会使用具体的对象的属性,例如上述的
people
,如果需要声明无法确定的键值对,可以用
Record<string, any>
类组件声明
上述声明一些常用的组件属性,我们来声明一个类组件,通常需要声明组件的
Props
和
State
interface Props {
message: string;
interface State {
count: number;
class App extends React.Component<Props, State> {
state: State = {
count: 0,
render() {
const {
message,
} = this.props;
const {
count,
} = this.state;
return (
{message} {count}
</div>
}
函数组件声明
我们都知道函数组件只需要一个
Props
,所以声明函数组件跟类组件还是有区别的,最简单的函数组件声明如下:
type Props = {
name: string;
const App = (props: Props) => {
return props.name;
const App: React.FC<Props> = (props) => {
return props.name;
const App: React.FC<Props> = ({ name }): string => {
return name;
}
组件children的类型
在 React 可以通过 children 来自定义子元素的渲染,我们可以这样声明:
interface Props {
children: React.ReactNode;
// 或者
interface Props {
children: JSX.Element;
// 或者
interface Props {
children: React.ReactElement;
// 或者
interface Props {
children: React.ReactNode | JSX.Element;
}
ReactNode和JSX.Element,ReactElement的区别
type ReactText = string | number;
type ReactChild = ReactElement | ReactText;
interface ReactNodeArray extends Array<ReactNode> {}
type ReactFragment = {} | ReactNodeArray;
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
type Key = string | number
interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
type: T;
props: P;
key: Key | null;
declare global {
namespace JSX {
interface Element extends React.ReactElement<any, any> { }
}
从上述定义看
JSX.Element
继承了
ReactElement
,只不过在 Props 和 State 声明指定为 any,更加通用,然而 ReactNode 更全面,通常我们 React 组件不一定是 JSX 元素,也可能是字符串,数字,空等类型,
所以 children 用 ReactNode 来定义就对了。
hooks声明
useState
声明 state 时,会接受一个泛型,如果我们不指定类型,通常会根据初始值自动推断出类型,下面的例子中,
isDone
会被推断为
boolean
类型。
const [isDone, setDone] = useState(false);
如果
useState
参数是空,ts 会推断这个 state 是
undefined
,接下来我们看下面的例子,我们手动设置 name 为 "",ts 会抛出警告
。「
Argument of type '""' is not assignable to parameter of type 'SetStateAction<undefined>'.」
function App() {
const [name, setName] = useState();
return (
<button
onClick={() => {
setName("");
click
</button>
{ name }
</div>
}
所以我们需要手动声明 state 的类型,即:
const [name, setName] = useState<string>();
下面是一些常见的 useState 声明:
const [user, setUser] = useState<User | null>(null);
setUser(newUser); // newUser 可以是 User 或者 null
const [user, setUser] = useState<User>({}); // 报错 Argument of type '{}' is not assignable to parameter of type 'User | (() => User)'.
const [user, setUser] = useState<User>({} as User); // 正常
本文为原创,未经授权,禁止任何媒体或个人自媒体转载
Javascript
React
typescript