TypeScript 项目实践 react/vue

485 阅读4分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

持续更新中...

vscode配置了ts校验,如果有js代码不想进行校验可以设置关闭

Xnip2021-11-21_00-08-35.jpg

tsc 是啥

tsc: TypeScript Compile 编译ts

如果想自动运行ts

  • 监听某个文件tsc xx.ts (-w: watch 监听)
tsc xxx.ts -w 
  • 监听某个文件夹,进入到文件下
tsc5 -w 

定义类型

定义数组

let abc: string[] = ['haha']
// 组合类型,数值不限制位置(区别于tuple元祖类型与值位置固定) 
let abc:(string | number | boolean)[] = [0, 'haha', 123, true]
let abc: Array<string | number | boolean| object> = [0, 'haha', {}, 123, true]
// any类型
let abc:any[] = [0, 'haha', {}, 123, true, class {}, underfined, null]
let abc:Array<any> = [0, 'haha', {}, 123, true, class {}, underfined, null]

定义对象

let abc:object = [] 
let abc:object = {}
let abc:{ name:string,age:number } = { name:'juejin',age:18 }

void 定义unll 跟 undefined

let abc: void = undefined
abc = null
let abc: null = null
let def: undefined = undefined
  • 函数中使用 voild就是义unll或者undefined
const abc = testFn(): voild | string => {
    return xxx
}
const abc = testFn(): null | string => {
    return null
}
  • 要是什么都不返回请使用never(voild就是义unll或者undefined)
const abc = testFn(): never => {
    throw new Error('error')
}

any unknown 跟 as 类型断言

let abc: any = 'juejin'
let d: string = abc // ok 没问题, any可以是任意类型,此时any就可以当string赋值给string类型
let abc: unknown = 'juejin'
let d: string = abc // 报错  abc不知道是什么类型,所以不能赋值给string类型
let d: string = abc as string // ok 没问题,as告诉abc是string, 就可以赋值给string类型

as类型断言, 利用unknown增加一个中间层定义成另外的类型

let abc: string = '123'
let d: number = abc as number // 报错 string不可以直接转number
let d: number = abc as unknown as number // OK 没问题  string => unknown => number 这个可以

定义函数

  • 设置默认值
const abc = testFn(a:number, b:number, c:number = 99) => {
    ...
}
type abcType = {name: string, ahe: number}
type abcFn = (user:abcType) => boolean
let actionUserFn: abcFn = (user: abcType): boolean => {
    return ture
}

元祖

let tuple:[strinf, nmumber, boolean] = ['hah', 123,  false]
// or
let tuple = ['hah', 123,  false]

枚举

enum SexType{
    BOY,   // 默认是0
    GITL,   //默认是1
}

  • 项目中使用

---------------导出---------------

/**
 * RoomStatusEnum 会议室类型
 * general = 1  普通
 * video = 2  视频
 * train = 3  培训
 */
enum BookRemindRoomStatusEnum {
    general = '1',
    video = '2',
    train = '3',
}
export { BookRemindRoomStatusEnum };

---------------使用---------------

import {BookRemindRoomStatusEnum} from '@/constData/enum';
const {train, video, general} = BookRemindRoomStatusEnum;

断言

  • 项目中使用
const resolveOnChange = (e: eventType, onChangeCallBack?: (event: eventType) => void) => {
    if (onChangeCallBack) {
        const event = e;
        onChangeCallBack(event as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>);
    }
};
a as Function

function fn(){
    let a = 'hhhh'
    let b = (x: number , y:number): number => x + y
    return [a ,b] as [typeof a, typeof b]  // 或者 return [a ,b] as const
}

as const 值类型

let a = 'juejin'
let b = 123
const arr = [a,b] // 数组类型 arr:[string,number] = [a,b]
// 添加as const , 变成了元祖类型
const arr = [a,b] as const  // const arr:readonly[string,number]
let a = 'juejin'
let b = 123 as const
let b = <const> 123 // 另一种写法 
// 添加as const , 变成了元祖类型
const arr = [a,b] as const  // const arr:readonly[string, 123]
let a = 'hahaha'
let b = 123
let c = [a, b] as const
let d = c[1] // let d: number 
d = 456 // 完全OK

非空断言 !

const el: HTMLInputElement = document.querySelector('.root')!
// 效果等同于
const el: HTMLInputElement = document.querySelector('.root') as HTMLInputElement

type 与 interface 该怎么用

首先说一下区别

  • 继承 合并
// interface 继承
interface a {
    name: string
}
interface b extends a {
   age: number
}

// type 合并
type A = {
    name: string
}
type B = {
   age: number
}
type C = A & B
type C = A | B

// type也可以通过implements定义class 
class NewOne e implements B {
    xxx
}

// interface 跟 type 也可以合并
type d = a * B

关于什么使用interface与type根据开发业务团队倾向定就行,使用没有太多区别 定义类的时候多数情况是接口为主

React 函数组件/类组件类型声明

  • 函数组件
import React, {FC} from 'react';

type ListProps = {
    data: string;
};

const RoomList: FC<ListProps> = (props) => {
    return(
        ...
    )
}
// or
const RoomList: FC<ListProps> = ({data}): string => {
    return(
        ...
    )
}
  • 类组件
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 (
            <div>
                {message}
                {count}
            </div>
        );
   }
}

请求接口

interface IResponseType<data = {}> {
    code?: number;
    status: number;
    msg: string;
    data: data;
}
interface IUser {
    name: string;
    age: number;
}
export const getData = () => {
    return request<IResponseType<IUser>>({
        url: '/api/list/user',
        method: 'get'
    });
};

后端返回接口定义

export interface ObjectAny {
    [key: string]: any;
}

export interface roomListType {
    code: number;
    data: ObjectAny;
    queryId: string;
    status: number;
}

React:Props类型声明

interface ModalButtonProps {
    children?: React.ReactNode | JSX.Element | React.ReactElement;  // React.ReactNode首选
    style: React.CSSProperties;
    type?: 'text' | 'default';
    className: string;
    disable: boolean;
    flickThreshold?: number;
    onClick: (val: string) => void;
    
    // 原生事件类型
    onChange: (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
    onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
    onClick: (event: React.MouseEventHandler<HTMLDivElement>) => void;
}

React hook 类型声明

const [isShowMore, setIsShowMore] = useState<boolean>(false);
const [name, setName] = useState<string>();
const [user, setUser] = useState<User | null>(null);
const [user, setUser] = useState<User>({} as User);