安装命令
npm i -g typescript 或者 yarn global add typescript
typescript 包:用来编译 TS 代码的包,提供了 tsc 命令,实现了 TS -> JS 的转化
验证是否安装成功:tsc –v(查看 typescript 的版本)
创建 ts 文件 => 2 编译 TS = > 3 执行 JS
说明:所有合法的 JS 代码都是 TS 代码,有 JS 基础只需要学习 TS 的类型即可
注意:由 TS 编译生成的 JS 文件,代码中就没有类型信息了。真正在开发过程中,其实不需要自己手动的通过tsc把ts文件转成js文件,这些工作应该交给webpack或 者vite来完成
原始类型:number/string/boolean/null/undefined
特点:简单,这些类型,完全按照 JS 中类型的名称来书写
let age: number = 18
let myName: string = '老师'
let isLoading: boolean = false
// 写法一: l
et numbers: number[] = [1, 3, 5]
// 写法二:
let strings: Array<string> = ['a', 'b', 'c']
能够通过联合类型将多个类型组合成一个类型
解释: | (竖线)在 TS 中叫做联合类型,即:由两个或多个其他类型组成的类型,表示可以是这些类型中的任意一种
let timer: number | null = null
timer = setInterval(() => {}, 1000)
// 定义一个数组,数组中可以有数字或者字符串, 需要注意 | 的优先级
let arr: (number | string)[] = [1, 'abc', 2]
类型别名(自定义类型) :为任意类型起别名
使用场景:当同一类型(复杂)被多次使用时,可以通过类型别名,简化该类型的使用
type CustomArray = (number | string)[]
let arr1: CustomArray = [1, 'a', 3, 'b']
let arr2: CustomArray = ['x', 'y', 6, 7]
函数的类型实际上指的是: 函数参数 和 返回值 的类型
// 函数声明
function add(num1: number, num2: number): number {
return num1 + num2
}
// 箭头函数
const add = (num1: number, num2: number): number => {
return num1 + num2
}
type AddFn = (num1: number, num2: number) => number
const add: AddFn = (num1, num2) => {
return num1 + num2
}
如果函数没有返回值,那么,函数返回值类型为: void
function greet(name: string): void {
console.log('Hello', name)
}
// 如果什么都不写,此时,add 函数的返回值类型为:
void const add = () => {}
// 这种写法是明确指定函数返回值类型为 void,与上面不指定返回值类型相同
const add = (): void => {}
// 但,如果指定 返回值类型为 undefined,此时,函数体中必须显示的 return undefined 才可以
const add = (): undefined => {
// 此处,返回的 undefined 是 JS 中的一个值
return undefined
}
使用函数实现某个功能时,参数可以传也可以不传。这种情况下,在给函数参数指定类型时,就用到可选参数了
// 数组的 slice 方法,可以 slice() 也可以 slice(1) 还可以 slice(1, 3)
function mySlice(start?: number, end?: number): void {
console.log('起始索引:', start, '结束索引:', end)
}
JS 中的对象是由属性和方法构成的,而 TS 对象的类型就是在描述对象的结构(有什么类型的属性和方法)
// 空对象
let person: {} = {}
// 有属性的对象
let person: { name: string } = {
name: '同学'
}
// 既有属性又有方法的对象
// 在一行代码中指定对象的多个属性类型时,使用 `;`(分号)来分隔
let person: { name: string; sayHi(): void } = {
name: 'jack',
sayHi() {}
}
// 对象中如果有多个类型,可以换行写:
// 通过换行来分隔多个属性类型,可以去掉 `;`
let person: { name: string sayHi(): void } = {
name: 'jack',
sayHi() {}
}
{
greet(name: string):string,
greet: (name: string) => string
}
type Person = {
greet: (name: string) => void
greet(name: string): void
}
let person: Person = {
greet(name) {
console.log(name)
}
}
对象的属性或方法,也可以是可选的,此时就用到可选属性了
type Config = {
url: string
method?: string
}
function myAxios(config: Config) {
console.log(config)
}
注意:直接使用 {} 形式为对象添加类型,会降低代码的可读性(不好辨识类型和值)
推荐:使用类型别名为对象添加类型
// 创建类型别名
type Person = {
name: string
sayHi(): void
}
// 使用类型别名作为对象的类型:
let person: Person = {
name: 'jack',
sayHi() {}
}
当一个对象类型被多次使用时,一般会使用接口( interface )来描述对象的类型,达到复用的目的
interface IPerson {
name: string
age: number
sayHi(): void
}
let person: IPerson = {
name: 'jack',
age: 19,
sayHi() {}
}
interface IPerson {
name: string
age: number
sayHi(): void
}
// 为对象类型创建类型别名
type IPerson = {
name: string
age: number
sayHi(): void
}
// 为联合类型创建类型别名
type NumStr = number | string
interface Point2D { x: number; y: number }
interface Point3D { x: number; y: number; z: number }
// 更好的方式
interface Point2D {
x: number; y: number
}
// 继承
Point2D interface Point3D extends Point2D {
z: number
}
场景:在地图中,使用经纬度坐标来标记位置信息
可以使用数组来记录坐标,那么,该数组中只有两个元素,并且这两个元素都是数值类型
let position: number[] = [116.2317, 39.5427]
let position: [number, number] = [39.5427, 116.2317]
// 变量 age 的类型被自动推断为:number
let age = 18
// 函数返回值的类型被自动推断为:number
function add(num1: number, num2: number): number {
return num1 + num2
}
let str1 = 'Hello TS'
const str2 = 'Hello TS'
通过 TS 类型推论机制,可以得到答案:
注意:此处的 ‘Hello TS’,就是一个字面量类型,也就是说某个特定的字符串也可以作为 TS 中的类型
任意的 JS 字面量(比如,对象、数字等)都可以作为类型使用
// 使用自定义类型:
type Direction = 'up' | 'down' | 'left' | 'right'
function changeDirection(direction: Direction) {
console.log(direction)
}
// 调用函数时,会有类型提示:
changeDirection('up')
// 创建枚举
enum Direction { Up, Down, Left, Right }
// 使用枚举类型
function changeDirection(direction: Direction) {
console.log(direction)
}
// 调用函数时,需要应该传入:枚举 Direction 成员的任意一个
// 类似于 JS 中的对象,直接通过 点(.)语法 访问枚举的成员
changeDirection(Direction.Up)
// Down -> 11、Left -> 12、Right -> 13
enum Direction { Up = 10, Down, Left, Right }
enum Direction { Up = 2, Down = 4, Left = 8, Right = 16 }
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
有代码提示
```javascript
let obj: any = { x: 0 }
obj.bar = 100 obj()
const n: number = obj
有时候你会比 TS 更加明确一个值的类型,此时,可以使用类型断言来指定更具体的类型。 比如,
const aLink = document.getElementById('link')
const aLink = document.getElementById('link') as HTMLAnchorElement
另一种语法,使用 <> 语法,这种语法形式不常用知道即可:
// 该语法,知道即可:
const aLink = <HTMLAnchorElement>document.getElementById('link')
泛型是可以在保证类型安全前提下,让函数等与多种类型一起工作,从而实现复用,常用于:函数、接口、class 中
创建一个 id 函数,传入什么数据就返回该数据本身(也就是说,参数和返回值类型相同)
function id(value: number): number { return value }
function id(value: any): any { return value }
泛型在保证类型安全(不丢失类型信息)的同时,可以让函数等与多种不同的类型一起工作,灵活可复用
定义泛型函数
function id<Type>(value: Type): Type { return value }
function id<T>(value: T): T { return value }
调用泛型函数
const num = id<number>(10)
const str = id<string>('a')
同样,如果传入类型 string,函数 id 参数和返回值的类型就都是 string
这样,通过泛型就做到了让 id 函数与多种不同的类型一起工作,实现了复用的同时保证了类型安全
// 省略 调用函数
let num = id(10)
let str = id('a')
默认情况下,泛型函数的类型变量 Type 可以代表多个类型,这导致无法访问任何属性
比如,id(‘a’) 调用函数时获取参数的长度:
function id<Type>(value: Type): Type {
console.log(value.length)
return value
}
id('a')
解释:
比如,将类型修改为 Type[] (Type 类型的数组),因为只要是数组就一定存在 length 属性,因此就可以访问了
function id<Type>(value: Type[]): Type[] {
console.log(value.length)
return value
}
// 创建一个接口
interface ILength { length: number }
// Type extends ILength 添加泛型约束
// 解释:表示传入的 类型 必须满足 ILength 接口的要求才行,也就是得有一个 number 类型的 length 属性
function id<Type extends ILength>(value: Type): Type {
console.log(value.length)
return value
}
泛型的类型变量可以有多个,并且类型变量之间还可以约束(比如,第二个类型变量受第一个类型变量约束)
比如,创建一个函数来获取对象中属性的值:
function getProp<Type, Key extends keyof Type>(obj: Type, key: Key) {
return obj[key]
}
let person = { name: 'jack', age: 18 }
getProp(person, 'name')
// Type extends object 表示: Type 应该是一个对象类型,如果不是 对象 类型,就会报错
// 如果要用到 对象 类型,应该用 object ,而不是 Object
function getProperty<Type extends object, Key extends keyof Type>(obj: Type, key: Key) {
return obj[key]
}
泛型接口:接口也可以配合泛型来使用,以增加其灵活性,增强其复用性
interface IdFunc<Type> {
id: (value: Type) => Type
ids: () => Type[]
}
let obj: IdFunc<number> = {
id(value) { return value },
ids() { return [1, 3, 5] }
}
实际上,JS 中的数组在 TS 中就是一个泛型接口。
const strs = ['a', 'b', 'c']
// 鼠标放在 forEach 上查看类型
strs.forEach const nums = [1, 3, 5] /
/ 鼠标放在 forEach 上查看类型
nums.forEach
解释:当我们在使用数组时,TS 会根据数组的不同类型,来自动将类型变量设置为相应的类型
技巧:可以通过 Ctrl + 鼠标左键(Mac:Command + 鼠标左键)来查看具体的类型信息