微软于3月16日发布了 TypeScript 5.0 版本。微软表示新版本体积更小、开发者更容易上手且运行速度更快。
TypeScript 可谓逐年火热,使用者呈现逐年上升的趋势,再不学起来就说不过去。
- 通过了解 TS 的四大好处,说服自己下定决心学习 TS
- 5 分钟学习 TS 最基础和常用的知识点,快速入门,包教包会
- 了解如何在 Vue 中使用 TypeScript,给 Vue2 开发者切换到 Vue3 + TypeScript 提供最基本的参考
- 如何将现有的 JS 项目改造成 TS 项目
1 学习 TS 的好处
1.1 好处一:紧跟潮流:让自己看起来很酷
如果你没学过 TS
你的前端朋友:都 2023 年了,你还不会 TS?给你一个眼色你自己感悟吧
你的前端朋友:哇,你们的项目已经用上 Vue3 + TS 啦,看起来真棒!教教我吧
1.2 好处二:智能提示:提升开发者体验和效率
当循环一个对象数组时,对象的属性列表可以直接显示出来,不用到对象的定义中去查询该对象有哪些属性。
下图是我们 OpenTiny 跨端跨框架前端组件库中的 Alert 组件,当在组件标签中输入 des
时,会自动提示 description
属性;当输入 @c
时,会自动提示 @close
事件。
1.3 好处三:错误标记:代码哪里有问题一眼就知道
1.4 好处四:类型约束:用我的代码就得听我的
2 极简 TS 基础,5分钟学会
2.1 基本类型
用得较多的类型就下面5个,更多类型请参考:TS官网文档
- 布尔 boolean
- 数值 number
- 字符串 string
- 空值 void:表示没有任何返回值的函数
- 任意 any:表示不被类型检查
let isDone: boolean = false;
let myFavoriteNumber: number = 6;
let myName: string = 'Kagol';
function alertName(name: string: void {
console.log(`My name is ${name}`;
}
默认情况下,name 会自动类型推导成 string 类型,此时如果给它赋值为一个 number 类型的值,会出现错误提示。
let name = 'Kagol'
name = 6
let name: any = 'Kagol'
name = 6
2.2 函数
看一下例子:
const sum = (x: number, y: number: number => {
return x + y
}
以上代码包含以下 TS 校验规则:
- 调用 sum 函数时,必须传入两个参数,多一个或者少一个都不行
- 并且这两个参数的类型要为 number 类型
- 且函数的返回值为 number 类型
? 可以表示该参数是可选的。
const sum = (x: number, y?: number: number => {
return x + (y || 0;
}
sum(1
如果将 y 定义为可选参数,则调用 sum 函数时可以只传入一个参数。
给 y 增加默认值 0 之后,y 会自动类型推导成 number 类型,不需要加 number 类型,并且由于有默认值,也不需要加可选参数。
const sum = (x: number, y = 0: number => {
return x + y
}
sum(1
sum(1, 2
2.3 数组
数组类型有两种表示方式:
-
泛型
表示法
类型 + 方括号
表示法
// `类型 + 方括号` 表示法
let fibonacci: number[] = [1, 1, 2, 3, 5]
// 泛型表示法
let fibonacci: Array<number> = [1, 1, 2, 3, 5]
这两种都可以表示数组类型,看自己喜好进行选择即可。
interface IArguments {
[index: number]: any;
length: number;
callee: Function;
}
function sum( {
let args: IArguments = arguments
}
IArguments
类型已在 TypeScript 中内置,类似的还有很多:let body: HTMLElement = document.body; let allDiv: NodeList = document.querySelectorAll('div'; document.addEventListener('click', function(e: MouseEvent { // Do something };
如果数组里的元素类型并不都是相同的怎么办呢?
let list: any[] = ['OpenTiny', 112, { website: 'https://opentiny.design/' }];
2.4 接口
接口简单理解就是一个对象的“轮廓”
interface IResourceItem { name: string; value?: string | number; total?: number; checked?: boolean; }
接口是可以继承接口的
interface IClosableResourceItem extends IResourceItem { closable?: boolean; }
这样 IClosableResourceItem 就包含了 IResourceItem 属性和自己的 closable 可选属性。
interface Alarm { alert(: void; } class Door { } class SecurityDoor extends Door implements Alarm { alert( { console.log('SecurityDoor alert' } }
如果类实现了一个接口,却不写具体的实现代码,则会有错误提示
2.5 联合类型 & 类型别名
看以下例子:
// 联合类型 let myFavoriteNumber: string | number myFavoriteNumber = 'six' myFavoriteNumber = 6 // 类型别名 type FavoriteNumber = string | number let myFavoriteNumber: FavoriteNumber
当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
function getLength(something: string | number: number { return something.length } // index.ts(2,22: error TS2339: Property 'length' does not exist on type 'string | number'. // Property 'length' does not exist on type 'number'.
上例中,length 不是 string 和 number 的共有属性,所以会报错。
function getString(something: string | number: string { return something.toString( }
2.6 类型断言
类型断言(Type Assertion)可以用来手动指定一个值的类型。
(animal as Fish.swim(
- 将一个联合类型断言为其中一个类型
- 将一个父类断言为更加具体的子类
- 将任何一个类型断言为 any
- 将 any 断言为一个具体的类型
我们一个个来看。
用途1:将一个联合类型断言为其中一个类型
interface Cat {
name: string;
run(: void;
}
interface F