美文网首页优美编程Web前端之路
前端的进化-追悼写TS砸过的键盘

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

作者: 小遁哥 | 来源:发表于2020-04-25 16:03 被阅读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定义的再好,翻开项目代码注释少的可怜不也很头大。

    相关文章

      网友评论

        本文标题:前端的进化-追悼写TS砸过的键盘

        本文链接:https://www.haomeiwen.com/subject/ywnhwhtx.html