ts 在项目中的使用
本次分享内容只涉及项目初始阶段如何引入ts及依赖插件的ts。
ts为类型系统,js没有类型,为了在开发阶段减少错误而引入的系统。
ts有单独的配置文件,一般放在项目目录下tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"experimentalDecorators":true,
"baseUrl": "./",
"paths": {
"@/*":["src/*"]
},
"types": ["vite/client"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}
ts与js运行时两套系统,虽然有时候代码是写在一起的,但他们运行时也是各自运行各自的代码。
比如 import {clone} from 'lodash'
,js系统引入的是clone函数,ts系统引入的是clone函数的类型。
1.ts 文件相关术语
- 模块文件: 含有 export 或者 import 的文件,文件名通常为:
xx.ts
import lodash from 'lodash'
console.log(lodash)
- 声明文件: 不含实际运行代码 文件名通常为
xx.d.ts
声明文件中
声明文件也可以是模块文件,但其不含实际运行代码,所以导出的都是类型声明
type A = {name:string}
declare const a:A
2. 引入ts
npm install typescript -D
typescript安装后,其自带浏览器上使用的所有对象的定义文件,比如dom,标签等
const div:HTMLDivElement = document.createElement('div')
3.引入依赖
3.1. 引入模块文件
引入模块文件通常使用 import
import {A} from './a.ts'
const a:A ={name:'gg'}
3.2. 引入非模块类的声明文件
使用三斜线 reference 引入,有常用两种方式 path和types
他们区别就是 types 一般引入外部依赖的声明,path 一般引入自己写的声明
比如外部声明文件位置为node_modules/@types/b/index.d.ts
,内容为type B={age:number}
,使用 path 和 types 引入方式如下:
/// <reference path="node_modules/@types/b/index.d.ts" />
/// <reference types="b" />
非模块的声明文件引入后为全局类型,可以直接使用const b:B={age:100}
这儿可以看出,与js文件引入相比,ts多了一项寻址策略,它中会自动寻找node_modules/@types下的文件。
3. 声明合并 官网地址
“声明合并”是指编译器将针对同一个名字的多个独立声明合并为单一声明。 合并后的声明同时拥有原先多个声明的特性
常见的使用例子为扩展属性
点击查看代码
interface C {
a:string
b:string
}
interface C {
c:string
}
const v:C = {a:'',b:'',c:''}
4. vite+vue3 工程中的常见配置
所有依赖插件,在官网中有详细说明如何使用类型。
4.1 vite 注入的全局类型
vite注入了例如import.meta.env.BASE_URL
,在import.meta中不存env属性,所以需要对ImportMeta
类型进行补充,
其文件位置在node_modules/vite/client.d.ts
。打开文件可以看到没有使用export 或者import。所以其为非模块声明,引入需要用到:
/// <reference types="vite/client" />
4.2 vue注入类型
vue类型文件在node_modules/vue/dist/vue.d.ts
,打开后可以看到有export 和import关键字,所有必须使用import引入,
引入一次后可以在其它文件模块文件使用类型。import 'vue'
4.2.1 注册全局组件
如果有注册全局组件,就需要对全局组件进行类型扩展。
如下扩展一个Layout组件
点击查看代码
import 'vue' // 此处说明此文件是模块文件
declare module 'vue' {
export interface GlobalComponents {
Layout: typeof import('./components/Layout.vue')['default']
}
}
4.2.2 注入.vue文件类型
当引入一个vue文件时,js编译器可以通过,但是ts却发现找不到。这是因为ts为.ts、.js、.tsx等文件已定义类型,vue文件需要手动定义类型
declare module '*.vue' {
import { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}
4.2.3. 别名设置
在某些时候,路径使用别名会很方便,比如将@
指向src
使用import data from '@/data'
访问src/data.ts,由于ts与js是两套系统,虽然js能够正常运行,但ts并不知晓'@/data'路径指向哪儿,所以需要在tsconfig.json中也配置路径别名,需要配置compilerOptions.baseUrl与compilerOptions.paths
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*":["src/*"]
},
}
}
此处地址转换 @/data
=> ${baseUrl}src/data
=> ./src/data
寻找到了正确地址。
4.3 编辑器配置
使用vscode + volar
volar能够自动按照tsconfig.json配置调用typescript做类型分析,不必将ts运行集成到项目中。也就是说类型系统由volar运行,js由项目本身运行。
5 vue3中api支持 官方文档
接口api工具 json2ts
将json转换成ts
遗留问题
在全局定义中 :declare let a:3
在其他文件中使用: let a = ''
不报错原因:declare let a 解释了一个全局的变量a 他的值是3,在模块文件中可以再次定义,就如fn内部能定义一个外部作用域的变量。当直接使用 a = ''
时出现报错