跳转到内容
aswind7
GitHub
Blog

TS项目实践笔记

本文为在项目实际开发中的笔记沉淀

参考文章

ts演练场 https://www.typescriptlang.org/play

ts不是银弹: https://zhuanlan.zhihu.com/p/407711884

react官方ts文档: https://react.dev/learn/typescript

react ts cheatsheet https://react-typescript-cheatsheet.netlify.app/docs/basic/setup

and this: https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/basic_type_example

ruanyifeng: https://wangdoc.com/typescript/intro

houdunren

如何学习?

  • 学习文档、博客来学习TS基础
    • 配合react ts官方文档
    • ruanyifeng 文档
  • 基于项目在实践中进行学习
    • vue+ts
    • react+ts

如何忽略ts检查

行内忽略

第1步: @ts-ignore 忽略下一行的ts检查

第2步: 禁用eslint (否则会出现 Do not use “@ts-ignore” because it alters compilation errors.)

// eslint-disable-next-line
// @ts-ignore
const a: object = 2;  // 这里类型赋值不对,ts原本会提示报错
console.log('a: ', a);

忽略整个ts文件

在文件最顶部加上这段注释

// eslint-disable-next-line
// @ts-nocheck

行内忽略+全局eslint配置更改

由于有时候想忽略单行,但是又不想每次都加eslint忽略,想一行// @ts-ignore就生效

第1步: 在eslintrc或者.eslintrc.cjs 添加配置 关闭

rules: {
    "@typescript-eslint/ban-ts-comment": "off",

第2步: @ts-ignore

// @ts-ignore
const a: object = 2;  // 这里类型赋值不对,ts原本会提示报错
console.log('a: ', a);

忽略eslint禁用any的规则

有时候项目会有Unexpected any. Specify a different type. 这往往是由于 .eslintrc.cjs 中的'plugin:@typescript-eslint/recommended',导致

// 解决办法1
// eslint-disable-next-line

// 解决办法2
eslintrc.cjs添加一条规则:
"@typescript-eslint/no-explicit-any": ["off"],

断言与any

有时候我们在某些场景下明确知道某个值的类型或者不希望ts检查,就可以使用他们来进行规避。

断言

// as 断言的意思就是用户断定这是什么类型

type T = 'a'|'b'|'c';
let foo1 = 'a';

// const bar:T = foo1; // 这个报错,原因是父类型不能赋值给子类型(父类型更宽泛 它是string 子类型是常量)

// 我们可以改为
const bar:T = foo1 as T

any

any类型很宽泛,接受任何类型的赋值(它也能赋值给任何类型,污染变量,unknown类型不会污染)

let foo1 = 'a';

let bar:any = foo1
bar = 2 //不报错

React与TS结合

推荐查看react ts cheatsheet https://react-typescript-cheatsheet.netlify.app/docs/basic/setup

组件

类型主要源自 @types/react @types/react-dom

function MyButton({ title }: { title: string }) {
  return (
    <button>{title}</button>
  );
}

// 更多的是提取为接口
interface MyButtonProps {
  title: string,
  disabled: boolean
}

function MyButton({ title }:MyButtonProps) {
  return (
    <button>{title}</button>
  );
}

// React.ReactNode 与 React.ReactElement区别?
React.ReactNode指任意类型,包含数字、字符串、null等;而React.ReactElement不包含,它只能是jsx;


interface MyComponentProps {
  style: React.CSSProperties; //行内样式
}

hooks

const [enabled, setEnabled] = useState<boolean>(false);

// 联合类型
type RequestState =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success', data: any }
  | { status: 'error', error: Error };

dom事件

最常用的dom事件: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/b580df54c0819ec9df62b0835a315dd48b8594a9/types/react/index.d.ts#L1247C1-L1373

// 这个回调函数类型是 React.ChangeEventHandler<HTMLInputElement>
const handleChange = useCallback<React.ChangeEventHandler<HTMLInputElement>>((event) => {
    setValue(event.currentTarget.value);
  }, [setValue])
  
  <input value={value} onChange={handleChange} />
    
    
 
    // 这个事件类型是 React.ChangeEvent<HTMLInputElement>
 function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
    setValue(event.currentTarget.value);
  }
  <input value={value} onChange={handleChange} />

一些理解

父子类型赋值

子类型能赋值给父类型, 反之则不行: 如果类型 B 可以赋值给类型 A,TypeScript 就认为 B 是 A 的子类型(subtyping),A 是 B 的父类型。子类型满足父类型的所有结构特征,同时还具有自己的特征。凡是可以使用父类型的地方,都可以使用子类型,即子类型兼容父类型。

const B = {x: 1, y: 1}
const A: {x: number} = B // 通过检查

const C: {x: number,y: number,z: number,} = B // 报错 Property 'z' is missing in type

void 和undefined的区别

在js中undefined原本是在window上的一个属性,在低版本浏览器可以被重写;而在高版本浏览器中,它如果是局部变量就也能被重写。所以一般三方库用void 0来替代undefined并且更简洁节省字节大小。

而在TS中:

  • void 用于函数的返回值类型,表示没有返回值。
  • undefined 表示变量值未被赋值,也可用于声明变量的类型。

void 不能用于声明变量或对象属性的类型,只能用于函数的返回值类型。

如何基于后端数据快速生成interface

  • json: 开源库生成对应的ts https://transform.tools/json-to-typescript
  • 后端数据的话,有node工具(参考开源自己实现),可以直接根据接口文档生成对应的请求方法,ts都是写好的;这么做的话,就对后端要求比较高了,因为函数入参都是根据接口文档生成的

实用代码片段

枚举-基于value获取key

const getKeyByValue = function (value: string): string | undefined {
  const foundEntry = Object.entries(LevelProps).find(([key, val]) => val === value);
  return foundEntry ? foundEntry[0] : undefined;
};

配置项

打开编译选项strictNullChecks

这个选项默认为false,是关闭了null和undefined校验的

// 为false时
let bar = undefined // 会被断言为any类型
let foo1 = 'a';
foo1 = undefined // 能通过
foo1 = null // 能通过

// 为true时
let bar = undefined // 仍然会被断言为any类型
let foo1 = 'a';
foo1 = undefined // 报错
foo1 = null // 报错

对象严格字面量检查

编译器选项suppressExcessPropertyErrors,可以关闭多余属性检查