在React函数式组件里使用TypeScript的类型检查
2019年12月12日 • ... • ☕️ 3 min read
自从React推出了Hooks,很多项目都慢慢变成了函数式组件,一是代码量降低,减少了很多生命周期调用和代码冗余;二是相对于class,还是function的写法更习惯。
强烈建议阅读:react-typescript-cheatsheet
props属性
函数式组件,一般都会以参数形式传入props。由于来源于上级组件或者其他地方,所以这部分会导致可控程度降低,如果加上有效的类型检查,就会好很多。除了TypeScript,React也提供了PropTypes的类型检查机制。先说TypeScript。
一般情况下,如果需要用到props里存储的内容,就需要先声明类型
type AppProps = {
name: string
};
const App = (props: AppProps) { return (<div>{props.name}</div>);
}
咋一看,这不是和PropTypes一样吗?
区别在于:TypeScript是编译时的类型检查,PropTypes是运行时的类型检查。这里有一篇回答,几种情况下不能相互替代。
但是,有一个插件,可以将TypeScript的类型检查,变为PropTypes。迷不迷。。
useState
通常useState的类型可以由设置的初始值来推测,但是如果初始为null就不行了。所以还是要指定一个类型。
const [state, setState] = React.useState({
foo: 1,
bar: 2
}); // state's type inferred to be {foo: number, bar: number}
const [value, setValue] = useState<number | null>(null);
如果这个类型的类型推测比较确定(比如上面例子中的state),那么使用的时候可以用typeof。
const setMethod = (obj: typeof state) {
setState(obj);
}
useEffect
useEffect
接受一个处理函数,(可选)一个清理函数,由于不用处理返回值,所以通常不用注意类型。但是有一个情况,就是箭头函数的时候,不带大括号,容易忽略这是一个返回值,使用setTimeout
这些默认会返回内容的时候就会有错误。
// setTimeout会返回一个timeoutID(数字),但是useEffect的返回内容必须是一个函数或者undefined
useEffect(
() =>
setTimeout(() => {
/* do stuff */
}, timerMs)
);
Event类型
如果直接在属性上写处理函数,通常TypeScript会推断出对应的类型。
const el = (
<button
onClick={event => { /* ... */
}}
/>
);
不过如果需要单独写处理函数,就需要自己指定类型了。
但是坏消息是React有自己的一套事件系统。其中一些名字虽然熟悉,但是内容不一样。React当然考虑到了这个问题,所以基本的属性还是有的,扩展内容根据需要取就好了。
如果不太想管具体事件类型,比如只想preventDefault
,可以直接用React.SyntheticEvent
。因为SyntheticEvent(合成事件)是通用的,所有浏览器事件都拿它包装了一层。
如果需要用event.target
(比如取值)的时候,单独给它指定对应类型即可
const changeValue = (e: React.SyntheticEvent) => { let element = event.target as HTMLInputElement;
let value = element.value;
setValue(value);
};
当然,也可以直接指定
const changeValue = (e: React.FormEvent<HTMLInputElement>) => { setValue(e.target.value);
};