本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
在使用typescript编写vue3时,我们是有一些配置和基本的和vue3有关的基础知识或者说和纯的typescript不同的地方,这些都在vue3的指南文档中进行了详细的说明,我们这里做个记录
volar
这个和vue2的区别是很明显的,vue2中是推荐的Vetur,现在vue3官方推荐的是Volar,那首先就是这两个扩展插件冲突的问题,那就是我们正常的开启vue3项目的时候要确保Vetur被禁用状态,TypeScript Vue Plugin (Volar) 就是我们上面提到的问题,支持引入.vue文件的,不然会报错
volar的 takeover模式
因为volar为了使vue单文件和TypeScript在一个文件中可以正常工作,创建了一个针对vue的TypeScript语言服务实例,但是同时,vscode对普通的.ts文件有内置的服务实例,这样的话,就是在一个项目中,是运行了两个语言服务实例的,这在普通的项目中可能并不会带来太大影响,但是当项目越来越大,性能消耗也就越来越大,两个实例就会带来影响,理想状态下,肯定是保持一个是最合适的,这个就是volar提供的功能了,volar提供了一个特别的模式,专门可以接管的功能,就是takeover的中文意思,在开启了这个模式后,volar能够用一个实例,同时对 .vue 和.ts的文件进行服务,开启takeover模式的步骤如下(windows系统):
- 用 Ctrl + Shift + P 唤起命令界面
- 在命令行输入: built 之后选择选项: Extensions: Show Built-in Extensions
- 选择后会自动跳转到扩展中,并自带前缀 @builtin 接着继续输入 typescript
- 跳出来的选项中点击第一个选项的设置按钮(右下角的齿轮)点击后选择: Disable(Workspace)
- 之后重新加载就可以了,之后打开vue或者ts文件就会自动启用takeover模式
配置tsconfig.json
手动配置的话有如下几个注意点:
compilerOptions.isolatedModules设置为true- 如果使用了选项式,这里不建议使用选项式,还是用组合式吧,我就不写了
- 如果我们使用了路径别名,那我们需要在tsconfig中再配置一遍,如下图所示,不然的话使用不报错,但是编辑器中会提示别名找不到
接下来我们记录下文档中对在setup中使用TS的注意事项:
为ref()标注类型
ref会根据初始化的值推到其类型:
// 这里就会自动推到year的类型是number,赋值给year其他类型就会报错
const year = ref(2023)
这时候如果我们想给ref指定更为复杂的类型,可以通过**Ref**这个类型
import { ref } from 'vue'
import type { Ref } from 'vue'
const year: Ref<string | number> = ref('2023')
// 除了上面这种我们还可以使用泛型
const year = ref<string | number>('2023')
如果使用了泛型,但是没有给默认或者初始化的值,那么类型推导出的是 泛型 | undefined
为reactive 标注类型
隐式的类型推导和ref是一模一样的,我们主要来着重说一下显式标注一个reactive的变量类型,需要使用接口
import { reactive } from 'vue'
interface Book {
title: string
year?: number
}
const book: Book = reactive({ title: 'vue3' })
为 computed() 标注类型
一样的,自动从计算函数的返回值上推导出类型,显式标注也是通过泛型:
const dou = computed<number>(()=> {
// 若返回值不是number类型会报错
})
为事件处理函数标注类型
还是和上面的一样,如果我们没有标注的话,参数是隐式的类型的,不过不是推导了,这里是默认标注的都是any类型,这会在tsconfig.json中如果设置了strict: true或 noImplicitAny: true,那么就会抛出一个TS错误,因此建议是显式的为事件处理函数的参数标注类型,此外,可能还需要显式的转换参数上的属性
function handleChange(event: Event) {
console.log((event.target as HTMLInputElement).value)
}
为provide、 inject标注类型
vue中提供了一个InjectionKey接口,继承自一个Symbol的泛型类型,可以用来在提供者和消费者之间同步注入值的类型
import { provide, inject } from 'vue'
import type { InjectionKey } from 'vue'
const key = Symbol() as InjectionKey<string>
provide(key, 'foo')
const foo = Inject(key) // foo的类型: string | undefined