由微软推出的TypeScript自从一推出就广受关注,现在无论开发前端React/Vue,还是后端API,很多项目中都广泛接受了TypeScript。下面介绍TypeScript在React props中的使用。

props中简单属性的声明
简单类型
type HelloProps = {
name: string,
age: number,
registered: boolean
}
export default function Hello(props: HelloProps) {
return <div>
Hello, {props.name}.
You are {props.age} years old.
{props.registered? 'You have registered.': 'You havenot registered yet.'}
</div>;
}
可选属性
这时可以使用 ‘?’ 来声明某个可选属性:
type HelloProps = {
name: string,
age?: number,
registered: boolean
}
在后面使用的时候,可以通过这种方式进行:
- 首先赋值0到变量中,
- 如果传递过来属性,则更新变量值
const {age = 0} = props
props中对象属性的声明
当然,也可以声明传递过来的是一个student对象:
type HelloProps = {
student: {
name: string,
age: number,
registered: boolean
}
}
export default function Hello(props: HelloProps) {
return <div>
Hello, {props.student.name}.
You are {props.student.age} years old.
{props.student.registered? 'You have registered.': 'You havenot registered yet.'}
</div>;
}
当传递给Hello组件的时候可以这样:
const stu1 = {name:'Luosi', age: 25, registered: false};
return (
<div className="App">
<Hello student={ stu1 }/>
</div>
);
props中数组类型属性的使用
首先在组件中的声明:
type HelloProps = {
students: {
name: string,
age: number,
registered: boolean
}[]
}
export default function Hello(props: HelloProps) {
return <div>
{
props.students.map(student => {
return (
<li>
Hello, {student.name}.
You are {student.age} years old.
{student.registered? 'You have registered.': 'You havenot registered yet.'}
</li>
)
})
}
</div>;
}
调用时:
function App() {
const students = [
{name:'Luosi', age: 25, registered: false},
{name:'Lucas', age: 18, registered: true},
{name:'Emily', age: 19, registered: true},
];
return (
<div className="App">
<Hello students={ students }/>
</div>
);
}
在props中使用联合类型union
在有些场合,需要对传递过来的参数值进行限定,这个时候可以使用union type:
type HelloProps = {
programme: 'UG' | 'PG';
}
export default function Hello(props: HelloProps) {
return <div>
<h2>{props.programme}</h2>
</div>;
}
这样在调用时只能传递UG或者PG,其余值都会报错:
<Hello programme='UG'/>
定义子元素类型
传递字符串到子元素
有些时候在调用一个React组件的时候,并非想要通过属性传递参数,而是在标签内传递,比如这样:
<Header>
Some text
</Header>
那么在Header组件中就需要这样声明:
type HeaderProps = {
children: string
}
export const Header = (props: HeaderProps) {
return <h2>{props.children}
}
传递React标签到子元素
首先,定义对应的props类型:
type HelloProps = {
children: React.ReactNode
}
export default function Hello(props: HelloProps) {
return <div>
{props.children}
</div>;
}
这里注意,自从React 17.x开始,可以不用引入React就直接使用。
其次,在调用时传递子元素:
<Hello>
<h2>This is a tilte</h2>
<p>This is a paragraph</p>
</Hello>
声明事件处理函数类型
不含参数和返回值的事件处理函数
type HelloProps = {
handleClick: () => void
}
export default function Hello(props: HelloProps) {
return <div>
<button onClick={props.handleClick}>Click me!</button>
</div>;
}
在调用时:
function App() {
const handleClick = () => {
alert('Clicked!');
}
return (
<div className="App">
<Hello handleClick={ handleClick }/>
</div>
);
}
指定具体事件类型
这时需要使用泛型来指定具体事件来源的类型
type HelloProps = {
handleClick: (event: React.MouseEvent<HTMLButtonElement>) => void
}
export default function Hello(props: HelloProps) {
return <div>
<button onClick={(event) => props.handleClick(event)}>Click me!</button>
</div>;
}
调用部分:
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
console.log('Clicked!', event);
}
同时传递其他参数
组件声明部分:
import React from "react";
type HelloProps = {
handleClick: (event: React.MouseEvent<HTMLButtonElement>, name: string) => void
}
export default function Hello(props: HelloProps) {
return <div>
<button onClick={(event) => props.handleClick(event, 'luosi')}>Click me!</button>
</div>;
}
调用组件:
function App() {
const handleClick = (event: React.MouseEvent<HTMLButtonElement>, name: string) => {
console.log('Clicked!', event, name);
}
return (
<div className="App">
<Hello handleClick={ handleClick }/>
</div>
);
}
输入组件的声明
组件部分:
import React from "react";
type HelloProps = {
defaultValue: string
handleChange: (event: React.ChangeEvent<HTMLInputElement>) => void
}
export default function Hello(props: HelloProps) {
return <div>
<input type='text' placeholder={props.defaultValue} onChange={props.handleChange} />
</div>;
}
调用部分:
function App() {
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
console.log(event.target.value);
}
return (
<div className="App">
<Hello defaultValue="init value" handleChange={ event => handleChange(event) }/>
</div>
);
}
传递styles
由于React已经将所有CSS属性封装好(React.CSSProperties),因此这时就可以充分利用TS的类型检测功能来提示我们非法的style属性声明。
组件定义:
type HelloProps = {
styles: React.CSSProperties
}
export default function Hello(props: HelloProps) {
return <div style={props.styles}>
Hello TypeScript
</div>;
}
调用部分:
<Hello styles={{border: '1px solid blue', backgroundColor: 'yellow'}}/>
在props的类型声明中中使用另一个组件类型
假设我们有Student组件:
type StudentProps = {
name: string
age: number
address: string
}
export default function Student(props: StudentProps) {
return (<div>
<p>Name: {props.name}</p>
<p>Age: {props.age}</p>
<p>Address: {props.address}</p>
</div>);
}
接下来想要做一个StudentFilter组件,对所有传递进来的Student进行筛选:
import React from 'react';
import Student from './Student';
export default function StudentFilter(props: React.ComponentProps<typeof Student>) {
return <div>
{props.age > 20? (
<Student {...props}/>
)
:
(<></>)
}
</div>;
}
可以看到,上面的类型声明中,就使用到了Student组件的类型:**props: React.ComponentProps
在声明之后,就可以直接使用类似:props.age 来访问其属性值了。
调用部分:
<div className="App">
<StudentFilter name="Paul" age={22} address="123 Fake Street"/>
<StudentFilter name="Lucy" age={18} address="124 Fake Street"/>
</div>