TypeScript学习 --- TS初体验

355 阅读4分钟

出现原因

编程的时候,我们有一个共识: 就是错误越早被发现越好

  1. 能在编写代码的时候被发现,就不要在编译阶段被发现(也就是能主动避免错误就不要让IDE来提示我们错误)
  2. 能在编译阶段的时候发现错误,就不要在运行阶段发现错误
  3. 能在开发时候发现的错误,就不要在测试的时候发现
  4. 能在测试的时候发现的错误,就不要在运行的时候被发现

js存在一个弊端:没有类型检测

// JS在调用的时候,并不会对传入的参数进行任何的校验
// 1. 不会进行参数类型的校验 (无论传入的参数是不是具有length属性)
// 2. 不会判断是否有传入参数 (运行的时候可能根本就没有任何的参数)

/*
  由于js并不会对上述内容进行调用,所以如果我们希望避免错误的发生
  我们需要手动对传入的参数的个数和类型添加校验代码
*/
function getLength(v) {
  console.log(v.length)
}

// 正常调用
getLength('Hello TypeScript')
getLength([1, 2, 3])

// 异常调用
getLength(123)
getLength()


// 如果js出现了错误,那么后续的代码就无法正常执行
// 所以js很可能因为没有类型约束而导致系统崩溃

// 后续代码 。。。。

如果此时我们需要为js传入的参数添加相关的限制,并且在编译阶段就发现对应的错误,以便于改正

在上述案例中:

  1. 设置getLength函数的参数v是必传属性
  2. 设置v必须是数组,字符串等有length属性的值

但是js无法在编译阶段发现上述问题,只能在运行阶段才能发现这些问题,此时很有可能代码已经交给了用户。

类型约束方案

创建的类型约束有:

2014年, Facebook提出的Flow,(vue2.x所使用的类型校验方案)

2014年,Microsoft提出的TypeScript (Vue3.x所使用的类型校验方案)

这里以TypeScript为主

简介

TypeScript 是拥有类型的JS超集,它可以被编译为原生JS代码

  1. TS是加强版的JS, 是JS的超集,完全支持原生的JS代码(包括最新的ES6,ES2021等代码)

    并在原生JS的语法上进行了扩展(如类型注解,枚举,元组等)

  2. TS无法在浏览器上直接运行,所以TS需要先编译为原生的JS后才可以运行在浏览器上,TS默认会将代码编译为ES3的代码,也可以修改配置,使其编译成ES5或ES6的代码

    2.1 常见的TS解析工具:

    • tsc (typescript compiler)--- ts官方提供的在命令行中解析ts的工具
    • ts-loader --- webpack中解析ts的loader
    • Babel --- 配置preset(preset是多个plugin的合集) --- @babel/preset-typescript

初体验

# 全局安装typescript,以便于在全局可以使用命令tsc
$ npm i typescript -g

# 查看tsc版本
$ tsc --version

# 编译
$ tsc <ts文件>

# 实时编译
$ tsc -w <ts文件>

# 只进行类型校验,但是不生成编译后的js文件 
$ tsc <源文件名或文件夹名> --noEmit

index.ts

let msg: string = 'Hello TS'

msg = 123 // => error


function getLength(v: string): number {
  return v.length
}

getLength('Klaus')

getLength(123) // => errro

// tips: 默认配置下,即使ts在编译的时候报错了,但是ts依旧可以成功被转换为js代码, 但是这段js代码在运行的时候,可能会出现错误。如果希望ts出现错误的时候,ts无法编译为js,需要修改ts的默认配置

环境搭建

搭建环境自动编译ts,并运行

ts-node

# ts-node 是一个工具库,可以解析ts文件,并直接在node环境下运行ts代码
$ npm i ts-node -g # 全局出现指令 ts-node
$ npm i @types/node tslib -g # ts-node所依赖的库 tslib -- ts的工具函数库 @types/node -- node针对于ts的类型定义

# 使用
$ ts-node foo.ts

在webpack中集成

# 安装
$ npm i ts-loader typescript webpack webpack-cli -D
$ npm i html-webpack-plugin webpack-dev-server -D

webpack.config.js

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: './src/index.ts',
  mode: 'development',

  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },

  /*
     ts中禁止我们使用带上ts后缀名的方式引入ts文件
     例如: import { foo } from './utils/foo.ts'
     但是如果去掉后缀名.ts的时候,webpack无法自动识别到对应的文件
     所以此时需要修改webpack的后缀识别配置,让webpack可以自动识别到ts后缀文件
     使import { foo } from './utils/foo'可以成功执行
  */
  resolve: {
    // 如果设置了扩展,默认的扩展配置会被覆盖
    // 所以需要加上原有的默认配置
    // 因为别的插件(如webpack-dev-server)在进行工作的时候,其内部代码在运行的时候是需要原本的默认配置的
    extensions: ['.ts', '.js', '.json']
  },

  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader'
      }
    ]
  },

  plugins: [
    new HtmlWebpackPlugin({
      template: './index.html'
    })
  ]
}

TS初体验

// 变量的声明
// var|let|const 标识符: 类型名称 = 值
let num: number = 123
// :number -> 类型注解

/*
  number 和 Number区别
  number => 数值类型
  Number => 数值的包装类 类型
*/
let num1: number = 321
let num2: Number = 321


// 类型推断 | 类型推导
// 如果在定义的时候直接赋值
// 此时会将值的类型自动作为标识符的类型,这个过程就被称之为类型推断或类型推导
let str = 'Klaus'
// str = 123 => error