浅识Typescript

242 阅读6分钟

01.TypeScript 是什么

  • TypeScript 是微软开发的开源编程语言, Type + JavaScript(type是类型 => 在 JS 基础之上,为 JS 添加了类型支持

  • 简称:TS,是 JavaScript 的超集

  • javascript中的变量,循环,函数在ts中正常使用,不需要额外学习语法

  • 学习ts主要是学习:

    • 1 类型
    • 2 与具体前端开发框架的结合使用

02typescript背景

背景:JS 的类型系统存在“先天缺陷”弱类型,JS 代码中绝大部分错误都是类型错误(Uncaught TypeError)类型错误的例子: var num = 18; num.toLowerCase();

这些经常出现的错误,导致了在使用 JS 进行项目开发时,增加了找 Bug、改 Bug 的时间,严重影响开发效率

  • 从编程语言的动静来区分,TypeScript 属于静态类型的编程语言JavaScript 属于动态类型的编程语言
    • 静态类型:编译期做类型检查
    • 动态类型:执行期做类型检查
  • 代码编译和代码执行的顺序:1 编译 2 执行
  • 对于 JS 来说:需要等到代码真正去执行的时候才能发现错误(晚)
  • 对于 TS 来说:在代码编译的时候(代码执行前)就可以发现错误(早)

\

并且,配合 VSCode 等开发工具,TS 可以提前到在编写代码的同时就发现代码中的错误,减少找 Bug、改 Bug 时间

03装包

安装编译 TS 的工具包:npm i -g typescript  或者 yarn global add typescript

    • typescript 包:用来编译 TS 代码的包,提供了 tsc 命令,实现了 TS -> JS 的转化

知识点学习,主要学习的就是类型。

类型注解

let a: number = 1
a = 100
a.toFixed(2)
console.log(a);
  • 代码中的 : number 就是类型注解 -为变量添加类型约束约定了什么类型,就只能给变量赋值该类型的值,否则,就会报错
  • 约定了类型之后,代码的提示就会非常的清晰

类型推论

在 TS 中,某些没有明确指出类型的地方,TS 的类型推论机制会帮助提供类型(简而言之有些场合下的类型注解可以不写)

类型推论的 2 种常见场景:

  1. 声明变量并初始化时
  2. 决定函数返回值时

数组类型

let arr1: number[] = [1, 2, 4, 6]
arr1.push(5)
console.log(arr1);


let arr: Array<string> = ['1', 'A', 'B', '3']

console.log(arr.join(','));

联合类型

数组中既有 number 类型,又有 string 类型

let x: number | string = 'a'
x = 100

let arr2: (string | number)[] = [1, 'g']

类型别名-type

作用

  1. 给类型起别名
  2. 定义了新类型

写法:type 别名 = 类型

// 类型别名

let y: (string | number | boolean)[] = [1, '2', false]
type Snb = (string | number | boolean)[]
let z: Snb = [12, '45', true]

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

// 普通函数
function fn(a: number = 100, b: number): number {
  return a + b
}
fn(1, 4)
// 箭头函数
const fn1 = (a: number = 100, b: number): number => {
  return a - b
}
fn1(77, 11)
console.log(fn1(77, 11));

如果一个函数没有返回值,此时,在 TS 的类型中,应该使用 void 类型,有如下三种情况会满足

  • 不写return
  • 写return ,但是后面不接内容
  • 写return undefined
// 统一定义函数的类型
type MyFunc = (a: number, b: number) => number

const add: MyFunc = (a, b) => { return a + b }
add(1, 8)
const fnn: MyFunc = (x, y) => { return x - y }
fnn(100, 34)
console.log(fnn(100, 34));

// 函数没有返回值加 :void
const updata = (a: number, b: string): void => {
  console.log(a, b);

}
updata(12, '12')
// 可选参数加?)
const data = (a?: number, b?: string): void => {
  console.log(a, b);

}
data()
data(1)
data(1, '2')

对象类型

jS 中的对象是由属性和方法构成的,而 TS 对象的类型就是在描述对象的结构

// 定义一个对象
  const obj: { name: string, age: number, address: number } = { name: '向阳', age: 18, address: 1 }

  // 之定义对象的类型
  type g = {
    name: string,
    age: number,
    address: number,
    greet: () => string
  }

  const obj1: g = {
    name: '吴迪',
    age: 12,
    address: 2,
    greet: function () {
      return "abc"
    }
  }

  const fn = (g1: g) => { g1.address = 1 }

对象可选属性

对象的属性或方法,也可以是可选的,此时就用到可选属性

 // 可选属性加?
  type stu = {
    name: string,
    gender: Gender,
    score?: number,
    height: number
    live: () => void
  }
  let stu1: stu = {
    name: '张三',
    gender: '女',
    // score:99,
    height: 178,
    live: () => { }


  }

接口类型

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

  • 解释:
    1. 使用 interface 关键字来声明接口
    2. 接口名称(比如,此处的 IPerson),可以是任意合法的变量名称,推荐以 I 开头
    3. 声明接口后,直接使用接口名称作为变量的类型
    4. 因为每一行只有一个属性类型,因此,属性类型后没有 ;(分号)

    接口。interface只能定义对象,可以继承。 type 不只能定义对象。不能继承

interface Istu {
    name: string
    age: number
  }
  const stulist: Istu = {
    name: '张三',
    age: 12
  }

继承

// 继承 extends
  interface Ipoint2D {
    x: number,
    y: number
  }

  interface Ipoint3D extends Ipoint2D {
    z: number
  }
  const P: Ipoint3D = {
    x: 100,
    y: 120,
    z: 130
  }

.元组类型

  • 场景:在地图中,使用经纬度坐标来标记位置信息
// 元组,一种特殊的数组,约定了元素的个数及类型
  let c1: [number, string] = [1, '2']

字面量类型

// 字面量
type sex = '男' | "女"

let s: sex = '男'
  • 使用模式:字面量类型配合联合类型一起使用
  • 使用场景:用来表示一组明确的可选值列表

枚举类型

  • 枚举的功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值
  • 枚举:定义一组命名常量。它描述一个值,该值可以是这些命名常量中的一个
// 枚举
enum Diraction {'up','down','left',"right"}


// 使用
let up:Diraction = Diraction.up


function f(g:Diraction){
  if(g===Diraction.down){
    return
  }
}

  • 解释:
    1. 使用 enum 关键字定义枚举
    2. 约定枚举名称以大写字母开头
    3. 枚举中的多个值之间通过 ,(逗号)分隔
    4. 定义好枚举后,直接使用枚举名称作为类型注解

## any 类型

  • 原则:不推荐使用 any!这会让 TypeScript 变为 “AnyScript”(失去 TS 类型保护的优势)
  • 因为当值的类型为 any 时,可以对该值进行任意操作,并且不会有代码提示
let obj: any = { x: 0 }

obj.bar = 100
obj()
const n: number = obj

## 类型断言

// 类型断言as

let img= document.getElementById('img')as HTMLImageElement

document.createElement('img')

img.src='www.xxx.com'
  • 解释:
    1. 使用 as 关键字实现类型断言
    2. 关键字 as 后面的类型是一个更加具体的类型(HTMLAnchorElement 是 HTMLElement 的子类型)
    3. 通过类型断言,aLink 的类型变得更加具体,这样就可以访问 a 标签特有的属性或方法了