文章目录
- 前言
-
-
- [1. interface和type差别](#1. interface和type差别)
- [2. omit剔除](#2. omit剔除)
- [3. 联合类型和交叉类型使用](#3. 联合类型和交叉类型使用)
- [4. 使用命名空间暴露类型声明](#4. 使用命名空间暴露类型声明)
- [5. 使用ForwardedRef传递ref](#5. 使用ForwardedRef传递ref)
- [6. 函数返回](#6. 函数返回)
- 7.Record
- 8.泛型使用
- [9. 继承](#9. 继承)
- [10. 定义函数返回类型为promise](#10. 定义函数返回类型为promise)
- [11. 返回reactNode](#11. 返回reactNode)
-
- 总结
前言
今天不讲实战,来讲一下我们专栏【 React+TS前台项目实战 】中用到的Typescript用法,比起网上那些直接概念式地讲,通过实战我们更能加深对Typescript方面相关知识的理解。
1. interface和type差别
这两种定义类型声明的主要区别在于interface定义的是对象,而type可以定义不限于对象的基本数据类型,联合类型,交叉类型等。
2. omit剔除
在项目封装input组件时,会使用到Omit去剔除声明中某个属性,再联合自己额外定义的属性,如下展示的是部分代码
c
type Props = Omit<ComponentPropsWithoutRef<"input">, "size"> & {
// 按下回车的回调
onEnter?: () => void;
// 清除输入框的回调
onClear?: () => void;
// 是否显示加载状态
loading?: boolean;
// 输入框大小
size?: "default" | "small" | "large" | undefined;
// 输入框前缀
hasPrefix?: boolean;
};
3. 联合类型和交叉类型使用
这里把联合和或一起举例,在Link链接组件中运用到了交叉类型的使用,组合自己定义的声明;在Search组件封装时,运用到了联合类型的使用,由于搜索结果类型不同,展示的数据结构不一样,这时候就可以用或把不同类型声明区分开来
c
// 交叉类型的使用
type LinkProps = Omit<RouterLinkProps, "ref"> & {
ref?: ForwardedRef<HTMLAnchorElement>;
to?: string;
className?: string;
children?: ReactNode;
};
import { Response } from '@/request/types'
import { Block } from '@/models/Block'
import { Transaction } from '@/models/Transaction'
export enum SearchResultType {
Block = 'block',
Transaction = 'ckb_transaction',
}
// 联合类型的使用
export type SearchResult =
| Response.Wrapper<Block, SearchResultType.Block>
| Response.Wrapper<Transaction, SearchResultType.Transaction>
4. 使用命名空间暴露类型声明
在请求封装中,使用到一系列类型声明,我们将他包装在了Response命名空间里面
c
export namespace Response {
export interface Response<T> {
data: T
meta?: Meta
error?: Error[]
}
export interface Error {
id: string
code: number
status: number
title: string
detail: string
href: string
}
export interface Meta {
total: number
pageSize: number
}
export interface Wrapper<A, T = string> {
id: number
type: T
attributes: A
}
}
5. 使用ForwardedRef传递ref
这里同样举例Link组件封装,做到了传递ref的功能
c
type LinkProps = Omit<RouterLinkProps, "ref"> & {
ref?: ForwardedRef<HTMLAnchorElement>;
to?: string;
className?: string;
children?: ReactNode;
};
const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
// ...
});
6. 函数返回
在弹窗组件Dialog的封装中,我们定义声明类型为返回void。
c
void onClose: () => void;
7.Record
简单讲,其实Record就是定义一个对象的一些key键名,然后定义键值的类型,在Searh组件的封装中,我们使用了它来定义搜索结果的数据类型声明。
c
export enum SearchResultType {
Block = 'block',
Transaction = 'ckb_transaction'
}
export type SearchResult =
| Response.Wrapper<Block, SearchResultType.Block>
| Response.Wrapper<Transaction, SearchResultType.Transaction>
Record<SearchResultType, SearchResult[]>
8.泛型使用
泛型是一个通用的数据类型参数,可代替任何类型,达到复用的效果。这里同样举了请求类型声明的定义上。
c
// 定义
export namespace Response {
export interface Wrapper<A, T = string> {
id: number
type: T
attributes: A
}
}
// 使用
type SearchResult =
| Response.Wrapper<Block, SearchResultType.Block>
9. 继承
这里定义了一个Props的类型声明,同时引用了ComponentProps类型声明,继承了其中div属性的类型声明
c
import { ComponentProps, ReactNode } from 'react'
interface Props<T> extends ComponentProps<'div'> {
data: T[]
}
10. 定义函数返回类型为promise
函数返回类型为promise,这个在Button组件的封装中使用了。
c
beforeChange?: (() => Promise<void>) | undefined;
11. 返回reactNode
这个类型通常用于函数组件的返回值,以便能够接受不同类型的内容,包括React元素、文本、数组或者null。这个在Modal组件的封装中使用了。
c
type Props = {
// 模态框内容
children: React.ReactNode;
};
总结
上面就是专栏【 React+TS前台项目实战 】目前为止主要用到的类型声明定义的方式,接下来会继续这个专栏文章的发布,还会继续用到其他方式进行类型声明定义,请持续关注。