typescript如何快速上手应用于vue项目的书写申明?
🙂前言
typescript 如何快速上手应用于 vue 项目?vue 项目引入了 typescript 后应该如何书写申明?
小波基于自己写 taro3+vue3+tsx+pinia+pnpm 微信小程序 的实际开发做个总结。
当然主要是快速上手,还有些进阶方面的小波也还在学习中。
typescript 虽然相对以前工作方式表面增加了一定工作量,但同时也解决了以前写法容易忽视的bug或是代码不严谨,不优雅,同时装了相关 vscode 插件还能自动推导类型,语法提示,类型信息的预校验,着实写完一次后还是感觉棒棒的。
🧐typescript 申明的作用
- 用来为已存在的 JS 库提供类型信息。
- 声明文件可以让我们不需要将JS重构为TS,只需要加上声明文件就可以使用系统。
- 在 TS 项目中使用第三方库时,就像在用 TS 一样,都会有代码提示、类型保护等机制,极大的提高了开发效率,降低了心智负担。
- 类型声明在编译的时候都会被删除,不会影响真正的代码。
🧐typescript 必备 vscode 插件
- volar 全家桶那是必须的
- JSON to TS(快速把后端接口返回的json数据转成ts申明,当然有些地方可能还是需要自己二次稍稍修改)
- ESLint
🤔typescript 如何引入项目
无论什么项目,首先安装 typescript
依赖
1 |
|
如果是 vue, 安装 vue-tsc
对于单文件组件,你可以使用工具 vue-tsc
在命令行检查类型和生成类型声明文件。 参看 vue3 官网文档
1 |
|
如果是 node 服务端
1 |
|
🤔typescript 配置文件 tsconfig.json
以小波写的 taro3+vue3+tsx 微信小程序项目为例
1 |
|
allowSyntheticDefaultImports
生动解释参考 TypeScript Tips (1) - allowSyntheticDefaultImports[4]
提示
通常装好 typescript 后,项目根目录还有个
types
文件夹,里面的global.d.ts
表示全局的申明。不需要通过
export
导出和Import
导入,这是typescript的默认规则如果要自己页面私有使用的申明,则自己在页面文件夹建个
x.d.ts
,同时需要使用export
导出和Import
导入配合使用当然在业务逻辑页面
x.ts
或者x.tsx
里写申明也是可以的,但是小波建议还是单独写在专用申明文件里吧。
😚typescript 申明vue项目实例书写规则
布尔值
1 |
|
数字
1 |
|
字符串
1 |
|
数组
用[]
表示数组,则类型放在前面
1 |
|
用 Array
表示数组,则类型用断言放在后面
1 |
|
提示
<>
类型断言有两种形式。 其一是“尖括号”语法:
1
2
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
as
语法
1
const list = [] as string[]
两种形式是等价的。 至于使用哪个大多数情况下是凭个人喜好;然而,当你在TypeScript里使用JSX时,只有
as
语法断言是被允许的。
元组 tuple
算是数组的扩展吧,相当于 const 常量一样,定死了数组位置和值
1 |
|
枚举
enum
类型是对 JavaScript 标准数据类型的一个补充。 像 C# 等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。
默认:从0开始递增
1 |
|
也可以自己指定初始值
1 |
|
场景1:字符串枚举,后端可能返回的json名称不标准或者不统一,可以通过枚举进行重新规范
1 |
|
any
有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any
类型来标记这些变量:
小波个人项目中使用,通常是第三方库方法返回无法更好完成ts申明的情况可以先用any
来解决报错,后续代码完成后ts会根据上下文推导成正确的申明再去除any
例如 vue3 的inject
获取全局变量时
1 |
|
void
某种程度上来说,void
类型像是与any
类型相反,它表示没有任何类型。
当一个函数没有返回值时,你通常会见到其返回值类型是 void
:
1 |
|
null 和 undefined
TypeScript里,undefined
和null
两者各自有自己的类型分别叫做undefined
和null
。
和 void
相似,它们的本身的类型用处不是很大:
小波个人总结就是尽量少用这个吧,原来 js 因为这个属性写判断已经很恶心了。
1 |
|
never
never
类型表示的是那些永不存在的值的类型。
例如, never
类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型;
变量也可能是 never
类型,当它们被永不为真的类型保护所约束时。
Typescript报错 类型“any”的参数不能赋给类型“never”的参数,更多时候小波遇见的场景,通常就是定义了变量却未申明,后续又对变量操作则容易出现这样的提示
1 |
|
object
object
表示非原始类型,也就是除number
,string
,boolean
,symbol
,null
或undefined
之外的类型。
例如小波在使用 nutui 组件的 nut-tabbar
时。组件返回的 item
,因为是组件固定返回所以项目中也未使用 interface
定义接口,那就直接用 object
1 |
|
1 |
|
接口 interface
通常使用在后端返回接口的值做申明
简单场景:函数的参数这样不需要公共使用则直接书写对象
1 |
|
公共场景:
1 |
|
提示
extends
表示继承,当然也可以继承多个
1
2
3
4
5
6
7
8
9
10
11
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface listObjType extends Shape, PenStroke {
total: string
listCount: number
getSuccess: boolean
}
?
表示 可选属性,也就是绑定申明的对象,即使没有list
这个值也不会报错
readonly
表示 只读
1
2
3
4
5
6
7
// 只要进行了1次绑定值,则后续都无法修改
const tempJson: listObjType = {
...
listCount: 1
}
tempJson.listCount = 10
// 报错:无法为“listCount”赋值,因为它是只读属性。ts(2540)
函数类型,可索引的类型,类类型,混合类型
这几个进阶类别可以自己查阅下官方文档[3],像函数类型我自己觉得没必要还用Interface
来写,这不是完全给自己增加难度系数么,明明直接用type
就行
函数
场景1:直接申明
1 |
|
场景2:外部引用
1 |
|
当然参数同样都是支持 ?
|
可选参数和默认参数
1 |
|
this
和箭头函数
简单讲,非箭头函数中的this值取决于这个函数是怎样被调用的,大概理解会是向上级查询
1 |
|
.bind()
更多说明参考 JS【详解】函数 .bind()
[6]
declare
以
declare
声明的变量和模块后,其他地方不需要引入,就可以直接使用了,和export
一起使用放在同一个 x.d.ts 则需要导出同时也是区分 js 和 ts 的标识
interface
和type
不需要使用declare
declare
的申明变量通常用在申明文件中做判断,例如typeof
1
2
3
4declare const ANIMATION = "animation";
export declare interface TransitionProps extends BaseTransitionProps<Element> {
type?: typeof TRANSITION | typeof ANIMATION;
}
type
type作用就是给类型起一个新名字,支持基本类型、联合类型、元祖及其它任何你需要的手写类型,常用于联合类型
1 |
|
type和interface的区别
和接口一样,用来描述对象或函数的类型(小波个人还是建议用interface)
1
2
3
4
5type User = {
name: string
age: number
};
type SetUser = (name: string, age: number)=>void;接口的继承
extends
type
可以通过交叉实现,当然interface
也能同时extends
type
的申明,type
也能交叉interface
的申明1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// type 交叉 interface
interface Name1 {
name: string;
}
type User = Name1 & {
age: number;
}
// type 交叉 == interface 的 extends
type Name2 = {
name: string;
}
type User = Name2 & {age: number}
// interface extends type
interface User extends Name2 {
age: number;
}
映射类型
1 |
|
重载,剩余参数,泛型,命名空间,声明合并等请自己查看下官方文档[3]或问问度娘,小波晚点再更新,也还在学习中…
🙂小波用到的相关参考资料链接
『旅行者』,帮小波关注一波公众号吧。
小波需要100位关注者才能申请红包封面设计资格,万分感谢!
关注后可微信小波,前66的童鞋可以申请专属红包封面设计。
微信
支付宝