优美编程Web前端之路

前端的进化-追悼写TS砸过的键盘

2020-04-25  本文已影响0人  小遁哥

导读

本文从解决问题的角度出发,讲述实际开发过程中遇到的一些困惑和解决方案。
之前尽管读过一些文章,也系统的看过教程,可当TS结合React,在加上个antd还是一头雾水!
有时候TS给出的提示让人崩溃,搜也搜不到!觉得TS麻烦!不知道类型是啥!感觉声明类型和导入太麻烦!
如果你有上述经历不妨看看这篇文章。

正文

一个经典的class组件

import React from "react";
import { Modal } from "antd";
interface AddModalProps {
  title: string;
}
interface AddModalState {
  isVisible: boolean;
}
class AddModal extends React.PureComponent<
  AddModalProps,
  AddModalState
> {
  constructor(props:AddModalProps) {
    super(props);
    
    this.state = {
      isVisible:true,
    }
  }
  public render() {
    const { isVisible } = this.state;
    const { title } = this.props;
    return (
      <Modal
        visible={isVisible}
        title={title}
        onCancel={this.onCancel}></Modal>
    );
  }
  private onCancel = () => {
    this.setState({
      isVisible: false,
    });
  }
}

export default AddModal;

声明AddModalProps我可以理解,为啥还要个AddModalState?这不麻烦吗

学习TS最好方式是自己去看定义文件

让我们把鼠标放在PureComponent上按下F12,鼠标悬浮上面也可以得到一些提示

 class PureComponent<P = {}, S = {}, SS = any> extends Component<P, S, SS> { }
    class Component<P, S> {

AddModalProps 传给了 PAddModalState 传个了 s,这里泛型起到关键作用,看看都约束了哪些东西

tslint won't let me format the sample code in a way that vscode likes it :( 

作者也是有困惑的

用别人的东西心态还是要摆正

一个参数的构造器

      constructor(props: Readonly<P>);

因为我们的构造器是覆盖了它,所以还是要声明类型
setState 函数

        setState<K extends keyof S>(
            state: ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
            callback?: () => void
        ): void;

这意味着当你setState是出现AddModalState中没有的key,或者类型不一致都会发生错误

    this.setState({
      isVisible: false,
      name:"xiaodun"
    });

这个提示确实不太容易读...


        render(): ReactNode;

自定义组件中是对render的 实现,所以不需要声明返回类型,会约束我们的返回

class中定义了一个未实现的方法,可以称之为抽象类

        state: Readonly<S>;

不必自己加个Readonly了,效果在于初始化后再一次的赋值

如果你在接口声明中未对属性加?号,没有初始化它会报错


AddModalState里面的引用类型使用时不需要再次声明
新增一个接口

interface Dog{
  name:string;
  age:number;
}

会提示你需要哪些属性


避免拼写

image.png
友情提示,有时候看不到是因为其它插件或设置影响到了,比如我打name的时候
image.png
其实name在上面...
使用的时候
image.png

还是泛型,按住Ctrl,把鼠标放到map上点进去

 map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];

U意味着你还可以约束返回的类型
往上找

interface Array<T> {

使用第三方库时不知道返回啥类型,也不知道要啥类型

使用Modal组件时,onClose还是onCancel记不清楚了,说实话,看官网真的累,同样F12进去

import OriginModal from './Modal';
import { ModalStaticFunctions } from './confirm';
export { ActionButtonProps } from './ActionButton';
export { ModalProps, ModalFuncProps } from './Modal';
declare type Modal = typeof OriginModal & ModalStaticFunctions;
declare const Modal: Modal;
export default Modal;

这变量名语义化的好,在进入ModalProps

image.png
这注释写的好!

可以先写然后自动导入



其实你用<开头的话,会看到这样

我也是刚刚才发现...,原谅我安装了太多自动提示的插件
我今天卸载了三个


有时候你得不到提示,可能是插件正在初始话、电脑CPU过载,比如频繁触发热更新...
我想要ref来控制它的显示
 private addModalRef = React.createRef<AddModal>();

还是泛型

function createRef<T>(): RefObject<T>;

鼠标放在createRef上也会告诉你

AddModal上定义一个函数

  public setVisible = (isVisible: boolean) => {
    this.setState({
      isVisible,
    });
  };

然后


实在在不行就

// @ts-ignore

as any

!. (不会是null)

比如类似这种问题,我想自己验证表单

interface APPState {
  validateStatus: string;
}
    this.state = {
      validateStatus:""
    }
image.png

说出来你可能不信,我一开始是进入到定义尝试着把它给导出来,是我想太多...
然后就看到这

declare const ValidateStatuses: ["success", "warning", "error", "validating", ""];
export declare type ValidateStatus = typeof ValidateStatuses[number];

然后神奇的脑回路就开始爱的魔力转圈圈
其实只要声明的时候改成

interface APPState {
  validateStatus: "";
}

我记住你了,字符串字面量类型

再看一下Input组件

  <Input onChange={this.onChange}></Input>
  private onChange = (e) => {
    console.log(e.target.value);
  };

这个e是什么类型呢?
如果你通过`onChange点进去

        onChange?: ChangeEventHandler<T>;
    type ChangeEventHandler<T = Element> = EventHandler<ChangeEvent<T>>;

不好意思,你看的是


还是要进Input
    handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void;

这表明你这么写是不用声明的


总结

TS虽然是大势所趋,但也要结合项目和团队成员的掌握情况,毕竟前端的业务特性摆在那里,面向对象的开发模式不是很匹配。

规则也没必要搞的过于严格,还在定义接口的时候可能不用TS已经写完了。

TS定义的再好,翻开项目代码注释少的可怜不也很头大。

上一篇下一篇

猜你喜欢

热点阅读