typescript- typescrip与react

对象的类型

接口 Interfaces 一般首字母大写

interface Person {
    readonly id: number; // 只读属性 不能修改
    name: string;
    age: number;
    age?: number;   // 可选
    [propName: string]: any; // 任意属性
    // 注意,
}
// 顺序 一般是 只读 -> 默认 -> 可选 -> 任意
let tom: Person = {
    name: 'Tom',
    age: 25
};

一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集:

interface Person {
    name: string;
    age?: number;
    [propName: string]: string;
}
let tom: Person = {
    name: 'Tom',
    age: 25,     // 报错 需要是 任意属性的子集
    gender: 'male'
};
  • 任意属性的值允许是 string,但是可选属性 age 的值却是 number,number 不是 string 的子属性,所以报错了
    只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候
interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}
let tom: Person = {
    name: 'Tom',
    gender: 'male'
};

tom.id = 89757;   // 报错,第一处是在对 tom 进行赋值的时候,没有给 id 赋值。 之后再赋值就报错

数组类型

「类型 + 方括号」表示法

let arr: number[] = [1, 2, 3, 4, 5]; // 表示 是数组, 并且数组元素只能为 number 类型

联合类型和数组的结合

// arr 表示 是数组, 并且数组元素只能为 number 和 string 类型
let arr: (number | string)[] = ['1', 'adaf', 2, 3, 5]

数组泛型

let arr: Array<number> = [1, 2, 3, 4, 5];

类数组

常见的类数组都有自己的接口定义,如 IArguments, NodeList, HTMLCollection 等
// error 函数中的 arguments 这也定义会报错
let args: number[] = arguments;
// success 改成
let args: IArguments = arguments;

函数类型

函数声明

function sum(x: number, y: number): number {
    return x + y;
}

函数表达式

let mySum = function (x: number, y: number): number {
    return x + y;
};
  • 这是可以通过编译的,不过事实上,上面的代码只对等号右侧的匿名函数进行了类型定义,而等号左边的 mySum,是通过赋值操作进行类型推论而推断出来的。如果需要我们手动给 mySum 添加类型,则应该是这样:
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};

类型断言

function getLength(something: string | number): number {
    // 将他断言为 string
    if ((<string>something).length) {
        return (<string>something).length;
    } else {
        return something.toString().length;
    }
}
  • 类型断言不是类型转换,断言成一个联合类型中不存在的类型是不允许的:
// error 
function toBoolean(something: string | number): boolean {
    return <boolean>something;
}
// Type 'number' is not comparable to type 'boolean'

内置对象

ECMAScript 的内置对象

Boolean、Error、Date、RegExp 等。

DOM 和 BOM 的内置对象

Document、HTMLElement、Event、NodeList 等。

泛型

  • 是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
function swap<T, U>(tuple: [T, U]): [U, T] {
    return [tuple[1], tuple[0]];
}

问题

  • type 和 Interfaces 的区别

React 中使用


import React, { MouseEvent, ReactNode } from 'react'
type Props = { 
 onClick(e: MouseEvent<HTMLElement>): void
 children?: ReactNode 
}
const Button = ({ onClick: handleClick, children }: Props) => (
  <button onClick={handleClick}>{children}</button>
)

高阶组件的使用方式

import React from 'react';
import { Form } from 'antd';
import { FormComponentProps } from 'antd/es/form';
interface IProps extends FormComponentProps {
  loading: boolean;
}
const Page: React.FC<IProps>  = (props) => {
  return (
     <div>Page</div>
  )
}
export default Form.create<IProps>()(Page)

对象类型取值

type DealWithProps = {
  onClose: Function;
  eventId: string;
  dealTime: any;
};
// 处理
const getOnDealWith = (parameObj: DealWithProps) => () => {
  // TODO 暂无接口
  for (let i in parameObj) {
    console.log(parameObj[i], typeof parameObj[i]);
      // 报错 
      /**
      Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'DealWithProps'.
  No index signature with a parameter of type 'string' was found on type 'DealWithProps'.ts(7053)
      **/
  }
};

Event 事件对象类型

常用 Event 事件对象类型:

• ClipboardEvent<T = Element> 剪贴板事件对象
• DragEvent<T = Element> 拖拽事件对象
• ChangeEvent<T = Element>  Change 事件对象
• KeyboardEvent<T = Element> 键盘事件对象
• MouseEvent<T = Element> 鼠标事件对象
• TouchEvent<T = Element>  触摸事件对象
• WheelEvent<T = Element> 滚轮事件对象
• AnimationEvent<T = Element> 动画事件对象
• TransitionEvent<T = Element> 过渡事件对象

Promise 类型

Promise<T> 是一个泛型类型,T 泛型变量用于确定使用 then 方法时接收的第一个回调函数(onfulfilled)的参数类型。

interface IResponse<T> {
  message: string,
  result: T,
  success: boolean,
}
async function getResponse (): Promise<IResponse<number[]>> {
  return {
    message: '获取成功',
    result: [1, 2, 3],
    success: true,
  }
}
getResponse()
  .then(response => {
    console.log(response.result)
  })

使用 react-router-dom

withRouter(ModuleLayout)

这类高阶组件的使用 方式,通常都需要继承到高阶组件 的 类型定义,如 antd Form.create 需要继承 FormComponentProps

import { FormComponentProps} from 'antd/lib/form/Form';
import { withRouter, Link, RouteComponentProps } from 'react-router-dom';
interface IProps extends RouteComponentProps<any> {
  basePath: string;
  menuList: IMenuItem[];
  children: JSX.Element;
}
function App(props: IProps){
    // 因为继承了 RouteComponentProps 所以可以获取 location
    const {location} = props;
    // xx
}
export default withRouter(ModuleLayout);

react 定义方法 useApi

/* eslint-disable no-param-reassign */
import { useRef, useEffect } from '@alipay/bigfish/react';
import { useImmer } from 'use-immer';
type Service<T> = () => Promise<T>;
type DependencyList = ReadonlyArray<any>;
interface Option<T> {
  onSuccess?: (data: T) => void;
  onError?: (errMsg: string) => void;
}
interface State {
  data: any;
  loading: boolean;
}
interface ResponseData<T> {
  success: boolean;
  data: T;
  message: string;
}
export default function useApi<T>(
  service: Service<ResponseData<T>>,
  dependencyList: DependencyList = [],
  option?: Option<T>
) {
  const initialState: State = {
    data: undefined,
    loading: false,
  };
  const [state, setState] = useImmer(initialState);
  const serviceId = useRef(0);
  useEffect(() => {
    const currentId = serviceId.current;
    setState(draft => {
      draft.loading = true;
      draft.data = null;
    });
    // 异步方法
    service().then(data => {
      // 组件卸载不更改
      if (currentId !== serviceId.current) {
        return;
      }
      if (!data.success) {
        // 错误
        setState(draft => {
          draft.loading = false;
          draft.data = null;
        });
        if (option && option.onError) {
          option.onError(data.message);
        }
      } else {
        // 成功
        setState(draft => {
          draft.loading = false;
          draft.data = data.data;
        });
        if (option && option.onSuccess) {
          option.onSuccess(data.data);
        }
      }
    });
    return () => {
      serviceId.current += 1;
    };
  }, dependencyList);
  return [state, setState];
}

react 使用 useRef

import React, { useRef, useState, FC } from '@alipay/bigfish/react';
import { message } from 'antd';
interface IProps extends FormComponentProps {
  isShow:boolean;
}
interface IUseRef extends HTMLDivElement {
  getAssets: Function;
}
const CreateStep: FC<IProps> = props => {
  const {
    form, isShow
  } = props;
  const refList = useRef<IUseRef>(null);
  const [current, setCurrent] = useState(1);
  function setNextStep() {
    const { current } = refList;
    const { getAssets } = current; // 类型“IUseRef | null”上不存在属性“getAssets”
  }
  return <div ref={refList}>xxxx</div>;
};
export default CreateStep;
  • 上面定义泛型的时候, 这个写法会报一个错误,因为 current 开始会是空的,后面 dom 挂在之后才会获取实例。

看下 useRef 源码定义, 也就是泛型的值就是 current 的结果

interface RefObject<T> {
   readonly current: T | null;
}
function useRef<T>(initialValue: T|null): RefObject<T>;
  • 并且 ref={ refLise } 需要传入的是 dom 元素节点,所以通过继承 HTMLDivElement 来得到 useRef 泛型。
    interface IUseRef extends HTMLDivElement {
    getAssets: Function;
    }

所以解决的方法。

方法一: 类型断言, 但是这样的代码其实是不严警的

 const { getAssets } = current as IUseRef;

方法二: 通过 if 判断,消除 current 为 null 的时候,如果不为 null 这里的类型就必定是 IUseRef 类型,所以可以取出 getAssets

let getAssets ;
if(current && current.getAssets){
  getAssets = current.getAssets;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vue-typescript-import-dts 是一个用于为 Vue.js 项目中的 TypeScript 文件生成类型声明文件的工具。在 Vue.js 项目中使用 TypeScript 进行开发时,我们经常需要为一些第三方库或自定义组件编写类型声明文件,以提供更好的代码提示和类型检查。 使用 vue-typescript-import-dts 工具可以自动分析 TypeScript 文件中的导入语句,并根据导入的模块生成对应的类型声明文件。这样,在使用该模块时,IDE 或编辑器就能提供准确的代码补全和类型检查。 例如,假设我们的项目中使用了一个名为 axios 的第三方库进行网络请求,但是该库并没有提供类型声明文件。我们可以通过 vue-typescript-import-dts 工具,在我们的 TypeScript 文件中导入 axios,并正确配置工具,它将自动为我们生成一个 axios.d.ts 类型声明文件。 具体使用 vue-typescript-import-dts 的步骤如下: 1. 在项目中安装 vue-typescript-import-dts,可以使用 npm 或 yarn 命令来安装。 2. 在 TypeScript 文件中,使用 import 语句导入需要生成类型声明文件的模块。 3. 在项目根目录下创建一个 .vue-typescript-import-dts.json 配置文件,用来配置生成类型声明文件的规则。可以指定生成的声明文件的输出路径、文件名等。 4. 运行 vue-typescript-import-dts 命令,它会自动扫描 TypeScript 文件中的导入语句,并根据配置生成相应的类型声明文件。 这样,在我们编写代码时,IDE 或编辑器就可以准确地为我们提供代码补全和类型检查的功能。这对于提高开发效率和代码质量非常有帮助。 总之,vue-typescript-import-dts 是一个便捷的工具,可以自动为 Vue.js 项目中使用的第三方库或自定义组件生成类型声明文件,提供更好的代码提示和类型检查功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值