① 你好ts:进入类型的世界

1 什么是 Typescript

1.1 编程语言的类型

  • 动态类型语言(js)

    • 数据类型检查发生在运行阶段
  • 静态类型语言(ts)

    • 数据类型检查发生在编译阶段

2 为什么要学习 typescript

2.1 ts 的优点

  • 程序更容易理解

  • 效率更高

  • 更少的错误

  • 包容性高

    • 完全兼容js

2.2 缺点

  • 增加学习成本 + 短时间内增加开发成本

3 安装 typescript

  • npm install -g typescript

  • 查看 tsc 版本:tsc -v

  • 编译 ts 文件:tsc fileName.ts

4 原始数据类型和 Any 类型

4.1 原始类型

  • Boolean

  • Null

  • Undefined

    • undefined 和 null 是所有类型的子类型
  • Number

  • BigInt

  • String

  • Symbol

let isDone: boolean = false

let age: number = 10
let binaryNumber: number = 0b1111 // es6支持2进制和10进制

let firstName: string = 'david'
let message: string = `hello, ${firstName}`

let u: undefined = undefined
let n: null = null

// undefined 类型的变量,可以赋值给 number 类型的变量
let num: number = undefined

4.2 Any 类型

  • 使用 any 类型失去了类型校验的功能
let notSure: any = 4
notSure = 'maybe a string'
notSure = true
notSure.myName
notSure.getName()

5 数组和元组

5.1 数组

  • 「类型 + 方括号」

  • 数组的项中不允许出现其他的类型

  • 数组的一些方法的参数也会根据数组在定义时约定的类型进行限制

let arrOfNumbers: number[] = [1, 2, 3]
// arrOfNumbers.push('123')
arrOfNumbers.push(3)

function test() {
  console.log(arguments);
  arguments[0]
  // let arr: any[] = arguments
}

5.2 元组

  • 元祖的表示和数组非常类似,只不过它将类型写在了里面 这就对每一项起到了限定的作用

但是写少一项就会报错,写多一项也会有问题

可以用数组方法添加数据项,但是只能添加相同类型的数据

let user: [string, number] = ['zhou', 123]
user.push(233, 'test')
// user.push(true)

6 Interface- 接口 初探

  • 对对象的形状进行描述

  • Duck Typing

6.1 定义接口 -- interface 关键字

// 定义接口 Person
interface Person {
  name: string;
  age: number;
}
// 定义变量 viking,类型是 Person
// 约束了 viking 的形状必须和接口 Person 一致
let viking: Person ={
  name: 'viking',
  age: 20
}

6.2 可选属性 -- 属性名?: 类型;

interface Person {
  name: string;
  age?: number;
}
let viking: Person = {
  name: 'Viking'
}

6.3 只读属性 -- readonly 关键字

interface Person {
  readonly id: number;
  name: string;
  age?: number;
}
viking.id = 9527

7 函数

  • 在 js 中,函数是一等公民

7.1 约定输入,约定输出

function add(x: number, y: number): number {
  return x + y
}

7.2 可选参数 -- 参数名?: 类型;

function add(x: number, y: number, z?: number): number {
  if (typeof z === 'number') {
    return x + y + z
  } else {
    return x + y
  }
}

7.3 函数本身的类型

// let add1: string = add wrong
const add2: (x: number, y: number, z?:number) => number = add

7.4 interface 描述函数类型

const sum = (x: number, y: number) => {
  return x + y
}
interface ISum {
  (x: number, y: number): number
}
const sum2: ISum = sum

8 类型推论 联合类型和 类型断言

8.1 类型推论(type inference)

let str = 'str'
// str = 123 // 不能将类型“number”分配给类型“string”

8.2 联合类型(union types)-- 类型1 | 类型2

  • 不确定一个联合类型的变量的类型时,只能访问此联合类型的 所有类型里共有的属性或方法
let numberOrString: number | string
numberOrString = 'abc'
numberOrString = 123
// numberOrString.length // let numberOrString: number | string

8.3 类型断言(type assertions) -- 变量 as 类型

解决只能使用共有方法问题

  • 用 as 关键字告诉 ts 编译器,你没法判断我的代码,但是我本人很清楚,这里我就把它看作是一个 string,你可以给他用 string 的方法
function getLength(input: string | number): number {
  const str = input as string
  if(str.length) {
    return str.length
  } else {
    const number = input as number
    return number.toString().length
  }
}

8.4 类型守卫(type guard)-- typeof

// ts 在不同的条件分支里面,智能的缩小了范围,这样我们代码出错的几率就大大的降低了
function getLength(input: string | number): number {
  if(typeof input === 'string' ) {
    return input.length
  } else {
    return input.toString().length
  }
}

9 类(Class)

  • 类Class:定义了一切事物的抽象特点

  • 对象Object:类的实例

  • 面向对象OOP三大特性:封装、继承、多态

9.1 定义类

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name
  }
  run() {
    return `${this.name} is running`
  }
}
const snake = new Animal('lily')
  • 继承的特性
class Dog extends Animal {
  bark() {
    return `${this.name} is barking`
  }
}

const xiaobao = new Dog('xiaobao')
console.log(xiaobao.run())
console.log(xiaobao.bark())
  • 重写构造函数 -- super
// 注意在子类的构造函数中,必须使用 super 调用父类的方法
class Cat extends Animal {
  constructor(name) {
    super(name)
  }
  run() {
    return 'Meow, ' + super.run()
  }
}
const maomao = new Cat('maomao')
console.log(maomao.run())

9.2 类成员的访问修饰符

  • public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的

  • private 修饰的属性或方法是私有的,不能在声明它的类的外部访问

  • protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的

10 类和接口 -- 完美搭档

10.1 类可以使用 implements 来实现接口

interface Radio {
  switchRadio(trigger: boolean): void;
}

interface Battery {
  checkBatteryStatus(): void;
}

class Car implements Radio {
  switchRadio(trigger: boolean) { }
}

class Cellphone implements Radio, Battery {
  switchRadio(trigger: boolean) { }
  checkBatteryStatus() { }
}

10.2 接口的继承 -- extends

interface RadioWithBattery extends Radio {
  checkBatteryStatus(): void;
}

11 枚举(Enum)

11.1 数字枚举

  • 数字枚举用关键字 enum 来定义,枚举成员会被赋值为从 0 开始递增的数字
enum Direction {
  Up,
  Down,
  Left,
  Right,
}
console.log(Direction.Up);
// 反向映射
console.log(Direction[0]);

11.2 字符串枚举

enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT',
}
const value = 'UP'
if(value === Direction.Up) {
  console.log('go up');
}

11.3 常量枚举

  • 只有常量值可以进行常量枚举,计算值不能进行常量枚举

提升性能

const enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT',
}
const value = 'UP'
if(value === Direction.Up) {
  console.log('go up');
}

12 泛型(Generics)

12.1 泛型

泛型 -- 类型的绑定

1. 泛型存在的意义

  1. 定义函数时必须给标识函数一个特定的类型或者 any
function identity(arg: number): number {
  return arg;
}
function identity(arg: any): any {
  return arg;
}

any 使我们丢失有关函数返回的类型信息

  1. 需要一种捕获参数类型的方法,以便我们也可以使用它来表示返回的内容
function identity<T>(arg: T): T {
  return arg;
}

2. 定义

function echo<T>(arg: T): T {
  return arg
}
const result2: string = echo('str')
const result3: number = echo(123)

function swap<T, U>(tuple: [T, U]): [U, T] {
  return [tuple[1], tuple[0]]
}
const result4 = swap(['string', 123])

12.2 约束泛型

泛型 -- 约定参数为特定类型

在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法

  1. 限定数组类型
function echoWithArr<T>(arg: T[]): T[] {
  console.log(arg.length);
  return arg
}
const arr = echoWithArr([1, 2, 3])
  1. 创建一个描述约束的接口 + extends 关键字
interface IWithLength {
  length: number
}

function echoWithLength<T extends IWithLength>(arg: T): T {
  console.log(arg.length);
  return arg
}

// 只要你有length属性就符合这个约束(只要你像鸭子你就是鸭子)
const str = echoWithLength('str')
const obj = echoWithLength({ length: 10 })
const arr2 = echoWithLength([1, 2, 3])
// echoWithLength(12) // 类型“number”的参数不能赋给类型“IWithLength”的参数

12.3 泛型在类和接口中的使用

泛型 -- 创建拥有特定类型的容器

1. 泛型在类中的使用

class Queue<T> {
  private data = [];
  push(item: T) {
    return this.data.push(item)
  }
  pop(): T {
    return this.data.shift()
  }
}
const queue = new Queue<number>()
queue.push(1)
console.log(queue.pop().toFixed());

2. 泛型在接口中的使用

interface KeyPair<T, U> {
  key: T
  value: U
}
let kp1: KeyPair<number, string> = { key: 1, value: 'string' }
let kp2: KeyPair<string, number> = { key: 'str', value: 2 }
let arr3: number[] = [1, 2, 3]
let arrTwo: Array<number> = [1, 2, 3]

13 类型别名,字面量 和 交叉类型

13.1 类型别名

let sum: (x: number, y: number) => number
const result = sum(1, 2)
type PlusType = (x: number, y: number) => number
let sum2: PlusType
const result5 = sum2(2, 3)
  • 支持联合类型
type StrOrNumber = string | number
let result6: StrOrNumber = '123'
result6 = 123

13.2 字符串字面量

提供一系列常量的写法

const str2: 'name' = 'name'
const number2: 1 = 1
type Directions = 'Up' | 'Down' | 'Left' | 'Right'
let toWhere: Directions = 'Left'

13.3 交叉类型

使用 type 扩展对象的方式

interface IName {
  name: string,
  gender: number
}
type IPerson = IName & { age: number }
let person: IPerson = { name: '123', gender: 1, age: 123 }

14 声明文件

使用第三方库

  • npm i -S @types/jquery
  • npm i -S redux

15 内置类型

15.1 内置类型

1. global objects

const a: Array<number> = [1, 2, 3]
const date = new Date()
date.getTime()
const reg = /abc/
reg.test('abc')

2. build-in objects

Math.pow(2, 2)

3. BOM DOM

let body = document.body
let allLis = document.querySelectorAll('li')
allLis.keys()
document.addEventListener('click', e => {})

15.2 Utility Types

interface IPerson {
  name: string
  age: number
}
let viking: IPerson = { name: 'viking', age: 12 }
type IPartial = Partial<IPerson> // Partial可选的
let viking2: IPartial = { name: 'viking' }
type IOmit = Omit<IPerson, 'name'> // Omit忽略
let viking3: IOmit = { age: 12 }
posted on 2022-05-27 17:24  pleaseAnswer  阅读(36)  评论(0编辑  收藏  举报