TypeScript基础知识 | 青训营笔记

118 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天

Typescript

什么是Typescript?

  • Typescript(简称TS)是JavaScript的超集(JS有的TS都有)

  • Typescript = Type + JavaScript(是在JS的基础上,为JS添加了类型支持)

    let age : number = 18
    

TS相比JS有何优势?

  1. 减少找Bug、改Bug时间
  2. 程序中任何位置的代码都有代码提示,随时随地的安全感,增强了开发体验。
  3. 强大的类型系统提升了代码的可维护性,使得重构代码更加容易。
  4. 支持最新的ECMAScript语法,优先体验最新的语法,让你走在前端技术的最前沿。
  5. TS类型推断机制,不需要在代码中的每个地方都显示标注类型,让你在享受优势的同时,尽量降低了成本。

除此之外,Vue3源码使用TS重写、Angular默认支持TS、React与TS完美配合,TypeScript已成为大中型前端项目的首先编程语言。

TypeScript常用类型

JS已有类型

  • 原始类型:number/string/boolean/null/undefined/symbol
  • 对象类型:object(包括:数组、对象、函数等)

TS新增类型

  • 联合类型、自定义类型(类型别名)、接口、元组、字面量类型、枚举、void、any等。
// 原始类型
let age : number = 18
let name : string = "猫猫"
let isLoading : boolean = false

//数组类型
//第一种写法:
let numbers : number[] = [1,2,3]
//第二种写法
let strings : Array<string> = ['a','b','c']

//联合数组类型
let arr : (number | string)[] = [1,'a',2,'b']

类型别名

指为任意类型起别名

  • 使用type关键字来创建类型别名
  • 类型别名可以使任意合法的变量名称
  • 创建类型别名后,直接使用该类型别名作为变量的类型注解即可。
type CustomArray = (number | string)[]

// let arr : (number | string)[] = [1,'a',2,'b']

let arr : CustomArray = [1,'a',2,'b']

函数类型

函数类型实际上指的是:函数参数和返回值的类型。

为函数指定类型的两种方式:

单独指定参数、返回值的类型
// 第一种方式
function add(num1 : number, num2 : number) : number {
    return num1 + num2;
}
// 第二种方式
const add1 = (num3 : number, num4 : number) : number => {
    return num3 + num4;
}
同时指定参数、返回值的类型
const add2: (num5 : number, num6 : number) => number (num5,num6) => {
    return num5 + num6;
}
  1. 函数没有返回值,返回值类型为:void

    function greet(name : string) : void {
        console.log('hello',name);
        
    }
    

    可选参数

    在可传不可传的参数名称后面添加 “?”

    注意:可选参数只能出现在参数列表的最后,必选参数后面不能再出现可选参数了

    对象类型

    JS中的对象是由属性和方法构成的,而TS中对象的类型就是在描述对象的结构(有什么类型的属性和方法。

image.png

let person : {name : string, age : number, sayHi() : void } = {
    name: 'Jack',
    age : 98,
    sayHi() {}
}

可选属性

比如我们在axios({...})时,如果发送GET请求,method属性就可以省略

function myAxios(config: {url : string ; method?: string}) {
	console.log(config)
}

接口

当一个对象类型被多次使用是,一般会使用接口(interface)来描述对象的类型,达到复用的目的。

interface IPerson {
    name : string
    age :number
    sayHi() : void
}

let person : IPerson = {
    name : 'Jack',
    age: 19,
    sayHi() {}
}

interface(接口)和type(类型别名)的对比:

  • 相同点:都可以给对象指定类型

  • 不同点

    接口,只能为对象指定类型

    类型别名,不仅可以为对象指定类型,实际上可以为任意类型指定别名。

typy IPerson = {
	name : string
	age : number
	sayHi() : void
}

接口继承

如果两个接口之间有相同的属性或方法,可以将公共的属性或方法抽离出来,通过继承实现复用。例如:

interface Point2D {
    x : number
    y : number
}
// interface Point3D {
//     x : number
//     y : number
//     z : number
// }
// 也可以这样写
interface Point3D extends Point2D {
    z : number
}

元组

元组类型可以确切地标记出有多少个元素,以及每个元素的类型

let position : [number, number] = [39.01,40,2]

类型推论(能省略类型注解的地方就省略)

声明变量并立即初始化值,此时可以省略类型注解

如果声明变量但没有立即初始化值,此时还必须手动添加类型注解

类型断言

  • 使用as关键字实现类型断言
  • 关键字as后面的类型是一个更加具体的类型(HTMLAnchorElement)
  • 通过类型断言,aLink的类型变得更加具体,这样就可以访问a标签特有的属性或方法了
const aLink = document.getElementById('link') as HTMLAnchorElement
aLink.href

字面量类型

// 这个变量是字符串类型
let str1 = "hello Ts"
//这个变量是"hello Ts"类型
const str2 = "hello Ts"

枚举

定义一组命名常量。它描述一个值,该值可能是这些命名常量中的一个。

  1. 使用enum关键字定义枚举
  2. 约定枚举名称、枚举中的值以大写字母开头
  3. 枚举中的多个值之间通过逗号分隔
  4. 定义好枚举后,直接使用枚举名称作为类型注解
  5. 类似于JS中的对象,直接通过"."语法访问枚举的成员
enum Direction {Up, Down, Left, Right}

function changeDirection(direction : Direction {
    cosole.log(direction)
}

注意:枚举成员是有值的,默认为从0开始自增的

枚举成员的值为数字的枚举称为数字枚举。(同理,可得到字符串枚举)

当然 也可以给枚举的成员初始化值

enum Direction { Up = 10, Down, Left, Right }
enum Direction { Up = 2, Down = 4, Left = 6, Right = 8}

枚举类型的特点:

image.png

any类型

原则:不推荐使用any!

typeof操作符

可以根据已有变量的值 获取该值的类型

let a : number = 1
console.log(typeof(a))

let p = { x : 1, y : 2}
function fun(point: typeof p){}
fun({ x: 4, y : 100})


let num : typeof p.x

TypeScript高级类型

class类

class Person {
    age : number
    gender = '男'
}
const p = new Person()
p.age
p.gender
构造函数:

为实例化对象属性初始化

  1. 成员初始化(比如age:number)后才可以通过this.age来访问实例成员
  2. 需要为构造函数指定类型注解,否则会被隐式推断为any
  3. 构造函数不需要返回值类型
实例方法
class Point {
    x = 1
    y = 2

    // 这里可以写任意自定义的方法
    scale(n : number) {
        this.x *= n
        this.y *= n
    }
}
const p = new Point()
p.scale(10)
console.log(p.x,p.y);
类的继承
  1. extends

    class Animal {
        move() {
            console.log("走两步……");
        }
    }
    class Dog extends Animal {
        name = "二哈"
        bark() {
            console.log("汪汪");
            
        }
    }
    const d = new Dog() 
    d.move()
    d.bark()
    
  2. implements

    interface Singable {
        sing() : void
    }
    class Person implements Singable {
        sing(): void {
            console.log("hello");
            
        }
    }
    
可见性修饰符
  • public:全部可见,默认是public
  • protected:仅对其声明所在类和子类中(非实例对象)可见
  • private:只在当前类中可见,对实例对象以及子类也是不可见的
只读修饰符readonly
  • 用来防止在构造函数之外对属性进行赋值,相当于把对象属性变成常量
  • 只能修饰属性不能修饰方法

类型兼容性

交叉类型

泛型和keyof

索引签名类型和索引查询类型

映射类型