第一章 ts特点

与js的区别

  • 以js为基础构建的语言
  • 一个js的超集
  • 可以在任何支持js的平台中运行
  • ts扩展了js,并添加了类型
  • ts不能被js解析器直接执行
    • 在编译过程中,ts还是编译成js

增加特性

  • 类型
  • 支持ES新特性
  • 添加ES不具备的新特性
  • 丰富的配置选项

第二章 ts开发环境搭建

下载node.js

下载链接:Node.js (nodejs.org)

1
2
// 检查node是否下载成功
node -v

命令安装ts

  • 全局安装
1
npm i -g typescript

创建并打开ts文件

  • 命令行创建空文件
1
touch helloTs.ts
  • 使用vscode打开文件

运行ts文件

  • 在ts文件的目录下打开控制台,输入

    1
    node helloTs.ts

编译为js文件

  • 在ts文件目录下打开控制台,输入

    1
    tsc helloTs.js

第三章 基本类型

可以让我们的变量赋予类型

  • let valuable: [type]
1
2
3
4
5
6
7
8
// 将变量a赋予类型number
let a: number = 20

a = 10
a = 33

// error,这个时候a的值不是number了
a = 'hello'
  • 如果变量的声明和赋值时同时进行的。ts可以自动对变量进行类型检测
1
2
3
4
5
6
// 这个时候已经赋予类型boolean了
let a = false
a = false

// 报错了
a = 123

可以对我们的函数赋予类型

  • 给参数赋予类型

    1
    2
    3
    4
    5
    6
    7
    8
    function sum (a: number, b: number) {
    reutrn (a + b)
    }

    console.log(sum(123, 456))

    // 报错
    console.log(sum(123, "456"))
  • 当然,参数个数也是严格把控了

    1
    2
    // 报错
    console.log(sum(123, 456, 789))
  • 函数表达式的赋予类型

    • 可以同时标注:
      • 参数个数与基本类型
      • 返回值类型
    1
    let fn: (a: number, b: string) => boolean

基本类型

  • 一览表
类型 例子 描述
number 123
string “hello”
boolean true
字面量 本身 限制变量的值就是该字面量的值
any * 任意类型
unknown * 类型安全的any
void 没有值(undefined)
never 没有值 不能是任何值
object {a: 1}
array [1, 2, 3] 任意的js数组
tuple [4, 5] 固定长度的数组
enum enum(A, B) 枚举

字面量的定义使用

1
2
3
4
// 将 10 作为给自己使用不能改变
let a: 10
// 报错
a = 11
  • 当然,我们可以当作枚举这么使用
1
2
3
4
5
6
let a: "male" | "female"
a = "male"
a = "female"

// 报错
a = "LGBT"
  • 一般用于连接多个类型
1
2
3
4
let a: string | number

// 报错
a = true

any的使用

  • 使用之后跟js很相似,不进行类型检错

unknown的使用

  • 使用之后表示未知类型的值

  • 与any的区别:any可以随意赋值给其他的类型,而unknown不行

  • 但是any和unknown被赋值的时候是极其相似的

  • unknown类型就是一个类型安全的any

    1
    2
    3
    4
    let a: string = "str"
    let b: unknown = "123"
    b = a // true
    a = b // false

类型断言

  • 语法

    • a = b as [type]
    • a = b
    1
    2
    3
    a = b as string

    a = <string>b
  • 用处:用于判断赋值的类型

never的使用

  • 一般用于设置函数的返回值【没有值】

  • 表示永远不会返回结果

  • 和void的区别:void返回是空,never是不返回,只throw错误

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
      function fn () : never {
    throw new Error("err")
    }



    ### object的使用

    - 最基本的定义就是设置变量是否为对象

    ```typescript
    let obj: object;
    obj = {} // ok
    obj = 123 // error
  • 当然,也可以这么表示,直接用object的符号{}表示【很像字面量法但却有点区别】

    1
    2
    let obj: {}
    obj = {name: 123} // ok
  • 此外,如果你想对object内部的对象的属性属性格式做一点要求,你也可以这么做【?表示可选】

    1
    2
    3
    4
    5
    let obj: {name: string, AGE?: number}

    obj = {age: 123} //error
    obj = {name: "smith", age: 123} // ok
    obj = {name: 123} // error
  • 你也可以对所有的属性的格式进行统一的要求

    1
    2
    3
    4
    5
    let c = {name: string, [propName: string]: string} // ok

    let num: {name: string, [propName: string]: number}// error 因为会和name发生冲突

    c = {name: "123", age: 123}// ok

array类型的声明

  • [type][]方法
  • Array方法
1
2
3
let e: string[] //声明字符串数组

let g: Array<number>// 声明数字数组

tuple类型

  • 定义:固定长度的数组

  • 声明方法:每一个都要声明,不然无法凸显长度和每一个元素的类型

    1
    2
    3
    let h: [string, number]
    h = ["123", 123]// ok
    h = [123]// error

enum类型

  • 用于定义枚举变量,可以用于定类型时设置字面量
1
2
3
4
5
6
7
8
9
10
enum Gender {
Male = 0,
Female = 1
}

let i: {name: string, gender: Gender}
i = {
name: "123",
gender: Gender.Male
}

我们甚至可以对类型起别名

1
2
3
4
type myT = 1 | 2 | string
let k: myT
k = false //error
k = "2eee"

第四章 编译选项

热编译

  • 我们应该要有一边修改一边编译的效果,下面是只更新一次的
1
tsc hello.ts
  • 我们需要在控制台将上述的命令行修改
1
tsc hello.ts -w
  • 有点类似于nodemon

全部执行

  • 不输入具体文件名即可
  • 接下来只需要执行tsc即可
1
tsc

编译配置环境

但是我们必须得有一个配置文件,不然无法执行

  • 需要一个tsConfig.json,是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译

  • include:用来指定哪些ts文件需要被编译

    **:表示任意目录

    *:表示任意文件

    1
    2
    3
    {
    "include": ["./src/**/*"]
    }
  • exclude:用来指定哪些文件不需要被编译

    默认值:[“node_modules”, “bower_components”, “jspm_packages”]

    1
    2
    3
    {
    "exclude": ["./src/hello/*"]
    }
  • complierOptions:用来指定编译器选项

    • target:指定编译js的版本 ESNext为最新版本
    • module:指定使用的模块化的规范
    • lib:用来指定项目中要使用的库,一般在项目中不使用它
    • outdir:指定编译之后生成的文件放置的目录
    • outFile:将代码合成一个文件,并且指定合称文件
    • allowJs:是否对文件进行js编译,默认为false
    • checkJs:是否将js依照ts语法规范检查,默认为false
    • removeComments:是否移除注释
    • noEmit:是否生成编译后的文件
    • noEmitOnError:报错之后是否生成编译后的文件
    • alwaysStrict:是否编译后的文件是否开启严格模式
    • noImplicitAny:不允许不明确【类型】的this,解决方法:this作为变量,类型为window
    • strictNullChecks:严格检查空值
    • strict:所有的严格模式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    {
    "compilerOprions": {
    "target": "ES6",
    "module": "commonjs",
    "lib": [],
    "outdir": './dist',
    "outFile": './dist/App.js',
    "allowJs": false,
    "checkJs": false,
    "removeComments": true,
    "noEmit": false,
    "noEmitOnError": true,
    "alwaysStrict": false,
    "noImplicitAny": false,
    "strictNullChecks": false,
    "strict": false
    }
    }

第五章 webpack打包ts代码

搭建初始开发环境(js)

  • 对空文件夹进行依赖注入

    1
    npm init -y
  • 安装webpack和ts的开发环境依赖

    1
    npm i -D webpack webpack-cli typescript ts-loader
  • 在项目根目录下创建webpack.config.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    const path = require('path')

    module.exports = {
    // 指定入口文件
    entry: './src/index.js',
    // 指定打包文件所在的目录
    output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bandle.js'
    },
    // webpack打包时要使用的模块
    module: {
    rules: [
    {
    // 制定规则生效的文件
    test: /\.ts$/,
    // 使用的东西
    use: 'ts-loader',
    // 要排除的文件
    exclude: /node-modules/
    }
    ]
    }
    }
  • 注意不要忘记了ts的配置

  • 在package.json的scripts中添加:"build": "webpack"

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    {
    "name": "my-webpack",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
    "ts-loader": "^9.2.6",
    "typescript": "^4.4.4",
    "webpack": "^5.64.0",
    "webpack-cli": "^4.9.1"
    }
    }

搭建自动生成HTML文件环境(HTML)

  • 根目录下输入

    1
    cnpm i -D html-webpack-plugin
  • webpack.config.js中引入html插件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    const path = require('path')
    const HTMLWebpackPlugin = require('html-webpack-plugin')

    module.exports = {
    // 指定入口文件
    entry: './src/index.js',
    // 指定打包文件所在的目录
    output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bandle.js'
    },
    // webpack打包时要使用的模块
    module: {
    rules: [
    {
    // 制定规则生效的文件
    test: /\.ts$/,
    // 使用的东西
    use: 'ts-loader',
    // 要排除的文件
    exclude: /node-modules/
    }
    ]
    },
    plugins: [
    // 配置Webpack插件
    new HTMLWebpackPlugin(),
    ]
    }
  • 执行命令行,可以生成HTML文件

    1
    npm run build
  • 当然,我们可以对插件进行传参

    1
    2
    3
    4
    5
    6
    7
    plugins: [
    new HTMLWebpackPlugin(options: {
    title: "myTitle",
    // 选择模板
    template: './src/index.js'
    })
    ]

编辑脚手架环境

  • 编辑开发运行环境

    1
    cnpm i -D webpack-dev-server
  • 在package.json中编辑【添加】命令

    1
    2
    3
    "scripts": {
    "start": "webpack serve --open chrome.exe"
    }
  • 在webpack.config.js中添加

    1
    mode: 'development'
  • 运行程序

    1
    npm start
  • 安装用于专门删除dist文件夹的环境,避免重复打包有旧文件

    1
    cnpm i -D clean-webpack-plugin
  • 在plugin中添加

    1
    2
    3
    4
    5
    plugins: [
    // 配置Webpack插件
    new HTMLWebpackPlugin(),
    new CleanWebpackPlugin(["dist"])
    ]
  • 设置引用模块

    1
    2
    3
    resolve: {
    extensions: ['.ts', '.js']
    }

考虑兼容性

  • 安装babel解决兼容性问题

    babel的作用就是将高版本的js转换为低版本的js

    1
    cnpm i -D @babel/core @babel/preset-env babel-loader core-js
  • 对webpack.config.js中的module进行修改

    • 我们可以在target中写出我们需要兼容的软件

    • corejs的作用,一些浏览器根本没有高版本的语法糖,比如ie没有Promise,那么此时就算转换低版本不会出现Promise,这个时候corejs可以将Promise的功能做一个低版本方式的替换

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    use: [
    {
    // 指定加载器
    loader: "babel-loader",
    // 设置babel
    options: {
    presets: [
    [
    // 指定环境的插件
    "@babel/preset-env",
    // 配置信息
    {
    targets: {
    "chrome": "88",
    },
    "corejs": "3",
    // 使用corejs的方式"usage"
    "useBuiltIns": "usage"
    }
    ]
    ]
    }
    },
    'ts-loader'
    ],
    • 注意,webpack有一个立即执行函数,他是箭头函数,但是箭头函数并不兼容ie,而且这个立即执行函数也没有经过babel处理过,我们要想让该立即执行函数也可以被处理,我们需要在output中加上:

      1
      2
      3
      environment: {
      arrowFunction: false
      }

函数的泛型

  • 当我们不知道我们需要什么类型的时候,就可以使用泛型,就有点类似于C++的函数模板
1
2
3
function fn<T>(a: T): T {
return a
}
  • 类型不确定,只有函数执行的时候我们才确定,还有最好的话最好执行函数的时候手动输入泛型
1
fn<String>(a: "hello")
  • 当然,泛型也不一定只有一个
1
2
3
4
function fn2 <T, K> (a: T, b: K): T{
console.log(b)
return a
}
  • 我们有的时候需要限制泛型的范围,我们需要用到用到extends字段

    extends是子集,泛型T必须要包含Inter的特性

1
2
3
4
5
6
7
8
9
10
interface Inter {
length: number
}

function fn3 <T extends Inter> (a: T): number {
return a.length
}

fn3(a: "hello")
fn3(a: 123)//error