一个函数的参数是vue的ref类型,该如何进行ts声明呢?

一个变量inputElref<HTMLInputElement>类型,将其传给了函数useCursor

// App.vue

import useCursor from './useCursor';

const inputEl = ref<HTMLInputElement | undefined>();

useCursor(inputEl)

useCursor中对inputEl的类型定义:

// useCursor.ts

type InputElementRef = Ref<HTMLInputElement | undefined>;

function useCursor(inputEl: InputElementRef) {
    // ...
}

优化一下,将类型定义共享:

// types.ts
export type InputElementRef = HTMLInputElement | undefined;
// App.vue

import { InputElementRef } from './types.ts';
import useCursor from './useCursor';

const inputEl = ref<InputElementRef>();

useCursor(inputEl)
// useCursor.ts

import { InputElementRef } from './types.ts';

function useCursor(inputEl: InputElementRef) {
    // ...
}

react的键盘事件对象如何定义类型?

type ReactKeyboardEvent = React.KeyboardEvent<HTMLInputElement>;

const onKeyDown = (e: ReactKeyboardEvent) => {
    // ...
};

<input onKeyDown={onKeyDown} />

ReactNode、ReactElement、ReactChild、ReactText、 ReactElement

type ReactText = string | number;
type ReactChild = ReactElement | ReactText;
type ReactNode = ReactChild | boolean | null | undefined;

ReactNode

当你希望一个函数或组件接受任何类型的React子节点时,你应该使用ReactNode
例如:
children,就适合用ReactNode

ReactElement

ReactElementReact.createElement()的返回值。
通常包含type(组件或DOM标签名)、props和可选的key属性。

当值为一个jsx内容时,你应该用ReactElement
例如:

const Demo = (): ReactElement => <div>Hello</div>

const div: ReactElement = <div />

资料:
when-to-use-jsx-element-vs-reactnode-vs-reactelement

Cannot find name 'defineProps'.Vetur(2304)

可能的原因之一是你启用了vscodeVetur插件,该插件对Vue3的支持不足导致。

Vue3中,VeturTypeScript Vue Plugin (Volar)已经被Vue - Official取代了,所以,确保禁用或者卸载掉前面两个插件,安装Vue - Official

拓展一个类型

ModalProps的基础上添加了一个isFullscreen属性。

import { Modal } from 'antd';

type ModalProps = React.ComponentProps<typeof Modal>
type ModalPropsWithFullscreen = ModalProps & { isFullscreen: boolean };

场景:
antd的组件基础上进行二次封装。
下面就是对antdModal组件进行二次封装,然后在默认props上添加了自定义的prop

const ModalEnhanced: FC<ModalPropsWithFullscreen> = (props) => {
  const { children } = props;

  return (
    <div>
      <Modal {...props}>
        {children}
      </Modal>
    </div>
  );
};

定义interface

定义一个interface类型,拥有基础的name、age、gender属性,并且可以自由扩展额外的属性。

下面两种定义方式是等价的,可以根据自己的喜好选择。

// 方式1 扩展性更好
type Person = {
  name: string;
  age: num;
  gender: string;
} & Record<string, any>;

// 方式2 代码更清晰
interface Person {
  code: string;
  age: num;
  gender: string;
  [key: string]: any;
}

断言

// 断言document.getElementById('btn')的返回值是一个HTMLElement元素
const btn = document.getElementById('btn') as HTMLElement;

DOM元素类型定义

const btn = document.getElementById('btn');

// Property 'style' does not exist on type 'Element'.ts(2339)
btn.style.display = 'none';

需要对btn进行类型声明

// 1 在声明变量时指定类型
const btn: HTMLElement = document.getElementById('btn');
btn.style.display = 'none';

// 2 使用as关键字进行类型断言
const btn = document.getElementById('btn') as HTMLElement;
btn.style.display = 'none';

两种方式都可以,但是第一种方式更推荐,因为第一种方式在编译阶段就会检查,而第二种是在运行时检查。

Record

Record用来定义对象的键和值的类型,也就是keyvalue
// 下面用Record定义了一个对象,键string类型,值为any类型。
type query = Record<string, any>;

const params: query = {
    name: 'Duo',
    age: 10,
    desc: undefined,
    children: [],
    target: null,
}

枚举

type Page = "home" | "about" | "contact";

// pageName为Page枚举类型,其值只能为home\about\contact三者其一。
const pageName: Page = 'home';

枚举也可以与Record组合使用

type Page = "home" | "about" | "contact";

// 此时,pages的key只能为home\about\contact三者其一。
const pages : Record<Page, string> = {
    home: '首页',
}

定义React组件

函数声明

interface TitleProps {
  name: string;
}

function Title({ name }: TitleProps) {
  return (
    <div className="container">
      {name}
    </div>
  );
}

函数表达式

import React from 'react';

interface TitleProps {
  name: string;
}

const Title: React.FC<TitleProps> = ({ name }) => (
  <div className="container">
    {name}
  </div>
);

热饭班长
3.7k 声望434 粉丝

先去做,做出一坨狗屎,再改进。