007 Umi 使用 TypeScript 提升开发者体验

3,308 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情

调整项目目录结构

调整项目目录结构

我本来计划是会有多个 examples 的,所以将项目写在了 boilerplate 目录下,有网友希望这个系列的产物能够最终作为能够支撑生产环境的脚手架,因此我们今天先调整一下我们项目的层级结构,其实就是将 boilerplate 目录下的文件(不包含 node_modules )都挪到根目录下面,后续执行就都不用 cd boilerplate 了。

修改 package.json 中的 nameumi4-course,然后从新执行 pnpm i 安装依赖。

安装完成之后,我们启动项目 pnpm start ,然后浏览器访问 http://127.0.0.1:8000/。正确看到页面就行。

在项目中使用 TypeScript 并不仅仅是为了让代码中的类型更加明确,对于有些还没学习过 TypeScript 的部分朋友有些本能的排斥,这是很正常的现象。 但是在项目中使用 TypeScript 其实和框架中使用 TypeScript 是完全不一样的,对于不懂 TypeSctipt 的朋友(当然现在不懂的挺少的吧!嘻嘻嘻)你就当做 js 写,只是把文件后缀从 jsx 换成 tsx,剩下的事情交给 VS Code。

给 Umi 项目添加 TypeScript 支持

你可以参照 TypeScript 官方文档,手动添加配置和使用,但是在 Umi 最简单方式还是使用微生成器,上一节课中,我们介绍了很多微生成器,其实如果你记不住或者说懒得记。你可以直接执行 npx umi g,Umi 会给出当前项目中支持的微生成器。

$ cd boilerplate
$ npx umi g

? Pick generator type › - Use arrow-keys. Return to submit.
❯   Create Pages -- Create a umi page by page name
    Enable Prettier -- Setup Prettier Configurations
    Enable Typescript -- Setup tsconfig.json
    Enable Jest -- Setup Jest Configuration
    Enable Tailwind CSS -- Setup Tailwind CSS configuration
    Enable Dva -- Configuration, Dependencies, and Model Files for Dva
    Generate Component -- Generate component boilerplate code
    Generate mock -- Generate mock boilerplate code
    Generator api -- Generate api route boilerplate code

我们通过上下方向键,选中我们需要的微生成器,比如现在我们选择 Enable Typescript -- Setup tsconfig.json.

✔ Pick generator type › Enable Typescript -- Setup tsconfig.json
info  - Write package.json
info  - Write tsconfig.json
 ... ...
Progress: resolved 727, reused 701, downloaded 0, added 13, done

devDependencies:
+ typescript 4.7.2

umi typescript 是否正确配置

判断 Umi typescript 是否正确配置非常的简单,只要看所有从 umi import 的内容是否全部“未找到”。

import { Link, useSearchParams, createSearchParams, useLocation } from "umi";
// 以上所有的引用都会标红,错误是 模块“"umi"”没有导出的成员“XXXXX”

如果未正确配置,则修改 tsconfig.json

修改 tsconfig.json

Umi typescript 部分的生成器还没有完全完成,后续还有 LSP 之类的功能,因此此时生成的 tsconfig.json 文件中的 paths 针对于项目的话是有错误的。

paths 改为正确的,能够指到 Umi 临时文件目录

    "paths": {
      "@/*": ["*"],
      "@@/*": [".umi/*"]
    },

改成

    "paths": {
      "@/*": ["./src/*"],
      "@@/*": ["./src/.umi/*"]
    },

如果你的 tsconfig 已经是正确的,那就不用修改。

修改文件后缀

修改文件名 src/pages/index.jsxsrc/pages/index.tsx 这时你将看到项目标红,鼠标移到标红的位置上,可以看到错误提示:““React”指 UMD 全局,但当前文件是模块。请考虑改为添加导入。ts(2686)” 要修复这个错误需要我们在文件的头部,引入 import React from "react";

引入之后发现文件中的错误修复了,但是 import react 这里又有一个新的错误,再次将鼠标移到标红的位置上,你讲看到一个新的错误提示:“找不到模块“react”或其相应的类型声明。ts(2307)”

一般 ts 提示找不到模块,要么就是没有安装,要么就是安装的库没有类型。我们可以在项目中安装对应的类型库,如

pnpm i @types/react --D

修复完之后,继续查看页面中存在标红的位置,你可以在 createSearchParams 看到标红,鼠标移上去看到一个错误:“类型“{ a: number; b: number; }”的参数不能赋给类型“URLSearchParamsInit | undefined”的参数。属性“a”的类型不兼容。不能将类型“number”分配给类型“string | string[] | undefined”。ts(2345)”

setSearchParams(createSearchParams({ a: 123, b: 456 }));
// ERROR:
// 类型“{ a: number; b: number; }”的参数不能赋给类型“URLSearchParamsInit | undefined”的参数。
//   属性“a”的类型不兼容。
//     不能将类型“number”分配给类型“string | string[] | undefined”。ts(2345)

123456 改成 '123''456'

自此,我们修复了当前页面的全部类型错误。看上面的行文,你会发现,我一直在强调“查看编辑器标红,然后鼠标移上去查看错误”,因为这个操作你要形成一种下意识的动作,一定要将页面中的标红全部清空,不能容忍哪怕一处“标红”,因为如果你容忍了一处“标红”,你就会下意识的忽略“标红”,后面你会发现,越复杂的页面你的“标红”错误更多。

还有聊聊好处,我们从 url 中取下来的值,会是全部都是字符串的,如果你在传参的时候写的是数字,也会被“默认”转成字符串,这在理解的时候又要耗费心智成本,所以这里类型提醒,会促使我们在传参的时候,就传递字符串。

以上操作重复一遍,修改 src/pages/user.jsxsrc/pages/user.tsx

智能提示和补全

先聊聊使用 typescript 最直观的好处,那就是智能提示和补全了,当你需要从一个库导出一个 Api 时,可能你只需要输入首字母,VS Code 就会自动罗列出这个库导出的全部 Api,如

import { u } from "umi";
// 当你输入一个 'u'
// 你将会看到如下列表
// useAppData
// useClientLoaderData
// useLocation
// useMatch
// useNavigate
// useOutlet
// useOutletContext,useParams,useResolvedPath ...

毫无疑问,这样确实可以极大的提升开发者体验。

不仅如此,Umi 还做的更多,Umi 是使用插件方式扩展框架能力的,意味着,很多能力和 Api 并不是内置集成在框架中的,所以 Umi 提供的所有 Api 的清单,和你当前项目使用到的所有插件直接相关。Umi 提供了 import all in umi 的能力,可以较少你少写很多的 import

这个的实现其实也很简单,在 umi 中导出 @@/exports 中的所有导出,我们前面配置 tsconfig.json 的时候,有写到 "@@/*": ["./src/.umi/*"],因此 @@/exports 就会被映射到 ./src/.umi/exports

插件中需要导出的 Api,通过通过 Umi 插件的 Api 写入 ./src/.umi/exports 文件中。所以如果后续你遇到一个 Api 无法工作或者提示找不到,你就可以直接先到这个文件下查看,“导出”是否被正确写入,这将有利于你定位和解决这一类问题。

当然如果你在向其他人请教问题或者提交 Issues 的时候,能够提供这些信息,也会大大的减少沟通成本。这将极大的提升框架开发人员的开发体验。

源码归档