点亮TypeScript技能树(一)

124 阅读3分钟

1. TypeScript

  • 简单介绍
  1. 以JavaScript为基础构建的语言
  2. 一个JavaScript的超集
  3. 可以在任何支持JavaScript的平台执行
  4. TypeScript扩展了JavaScript并添加了类型

1.1 TypeScript的基本安装使用

  1. 安装node.js
    1. nodejs.cn/
  2. 使用npm全局安装TypeScript
    1. npm install -g typescript
  3. 创建一个.ts文件
    1. 比如新建一个helloTS.ts文件,编写内部的逻辑
  4. 使用tsc对当前新建的ts文件进行编译
    1. 使用终端运行 tcs helloTS.ts 这个文件后就会编译出helloTS.js文件

1.2 TypeScript的基本类型

类型描述
number任意数字
boolean布尔值true和false
string任意字符串
字面量限制变量的值就是该字面量的值
any任意类型
unknown类型安全的any
void没有值(或undefined)
never不能是任何值
object任意的js对象
array任意js数组
tuple元素,表示一个已知元素数量和类型的数组,各元素的类型不必相等
enum枚举

1.2.1 number类型

  1. 和JavaScript一样,TypeScript里的所有数字都是浮点数。这些浮点数的类型是number,除了支持十进制和十六进制字面量,TypeScript还支持ECMAScript2015中引入的二进制和八进制字面量
  2. 代码练习
// 定义变量为number类型,同时又初始化赋值
let num1: number = 111
let num2: number = 0xf00d
let num3: number = 0b1010
let num4: number = 0o744

// 定义了变量的类型是number类型
let num5: number
num5 = 789

// 通过字面量的方式定义变量的值, 变量的值只能是字面量定义的初始值
let num6: 123
num6 = 123

1.2.2 布尔值

  1. 最基本数据类型 true/false值
  2. 代码练习
// 初始化
let isShow: boolean = false
isShow = true

let isLoading: boolean
isLoading = false
isLoading = true

// 字面量方式定义时,设置为boolean类型的false值,使用时不能更改为true
let isShowToast: false
isShowToast = false

1.2.3 字符串类型

  1. 和JavaScript一样,可以使用单引或双引,也可以使用模板字符串
  2. 代码练习
// 初始化
let str1: string = 'hello'
str1 = 'world'

let str2: string
str2 = 'hello TS...'

// 使用模板字符串
let username: string = "wukong"
let count: number = 123
let str3: string = `excuse, Are you ${username} ? `

1.2.4 联合类型

  1. 可以使用 | 来链接多个类型
  2. 代码练习
let sex: "male" | "female";
sex = "male";
sex = "female";
// 使用 | 链接多个类型 
let list: string | boolean | number
list = "hello"
list = true
list = 123

1.2.5 any

  1. 表示可以是任意类型,将一个变量设置为any类型后,相当于对该变量关闭了TS的类型检查
  2. 当变量是any类型时,赋值给任何类型的变量不会报错
  3. 代码练习
let noSure: any;
// 声明变量不指定类型,则TS解析器会自动判断类型为any (隐式的any)
let yesSure;
noSure = 1;
noSure = false;
noSure = "123";
noSure = [1, 2, 3];

yesSure = 1;
yesSure = true;
yesSure = "123";
yesSure = [1, 2, 3];

1.2.6 unknown

  1. 当声明变量类型是unknown时,相当于是一个类型安全的any.unknown声明的变量不能直接赋值给其他变量
  2. 代码练习
let e: unknown
e = 123
e = true
// 如果不对变量e不做类型检查直接赋值给square时,会出错
if( typeof(e) == "string"){
  square = e
}

1.2.7 类型断言

  1. 当我们清楚地知道一个实体具有比它现有类型更确切的类型时,可以通过类型断言这种方式告诉编译器。
  2. 类型断言有两种形式,其一是"尖括号"语法,另一个为as语法
  3. 代码练习
// 第一种写法 使用尖括号告诉编译器实际的类型
let someValue: unknown = "this is string";
let strLength: number = (<string>someValue).length;
// 第二种写法 使用as语法实际的类型
let someValue2: unknown;
someValue2 = "this is string...";
let strLength2: number;
strLength2 = (someValue2 as string).length;

1.2.8 Void

  1. 在某种程度上来说,void类型像是与any类型相反,它表示没有任何类型。当一个函数没有返回值时,通常返回值类型时void.
  2. 声明一个void类型的变量没有什么大用,因为只能为它赋值undefined和null 3.代码练习
function fn(num: unknown) {
  if (typeof num == "number") {
    return 123;
  } else {
    return "123";
  }
}
// void用来表示空,以函数为例,就表示没有返回值的函数
function fn1():void {}
// 当返回值是null或undefined
function fn3(): void {
  return undefined;
}
// 声明一个void类型的变量
let enable: void 
enable = undefined

  1. Null和Undefined
  • TypeScript里,undefined和null两者各自有自己的类型分别叫做undefined和null。和void相似,他们的本身的类型用处不是很大:
  • 默认情况下nullundefined是所有类型的子类型。就是说可以把nullundefined赋值给number类型的变量.
  • 当指定了--strictNullChecks标记,nullundefined只能赋值给void和他们各自。

1.2.9 Never

  1. never类型表示的是那些用不存在的值的类型,例如抛出异常或根本就不会有返回值
  2. never类型是任何类型的子类型,也可以赋值给任何类型。即使any也不可以赋值给never
  3. 代码练习
function fn4(): never{
  throw new Error('程序挂了')
}

1.2.10 Object

  1. object表示非原始类型。
  2. 声明对象、函数的语法
// 声明a的类型为对象,添加一个属性
let a: { name: string };
a = { name: "sunwuxong" };
// 声明b的类型为对象,添加可选属性age,通过?的形式表示可选属性
let b: { name: string; age?: number };
b = { name: "ershixion" };
// 声明c的类型为对象,添加任意属性
let c: { name: string; [propName: string]: any };
c = { name: "shashidi", gender: "female" };

// 使用箭头函数的形式来声明函数的结构
let d: (a: number, b: number) => number;
d = function (n1: number, n2: number) {
  return n1 + n2;
};

1.2.11 Array

  1. TypeScript像JavaScript一样可以操作数组元素.有两种方式可以定义数组。
  2. 第一种,可以在元素类型后面接上[],表示由此类型元素组成的一个数组
  3. 第二种,使用数组泛型, Array<元素类型>
  4. 代码练习
// 第一种方式定义数组
let arr1: number[]
arr1 = [1,2,3,4]
// 第二种方式定义数组
let arr2: Array<string>
arr2 = ['1','2','3']

1.2.12 元组Tuple

  1. 元组类型允许表示一个已知元素数量和类型的数组,个元素的类型不必相同。
// 声明元组tuple
let arr3: [ string, boolean ]
arr3 = ["abc", false]
// 访问一个已知索引的元素
console.log(arr3[0].substr(1));
console.log(arr3[1] == false);

1.2.13 枚举enum

  1. enum类型是对JavaScript标准数据类型的一个补充。可将一个个可读的属性列举出来
  2. 代码练习
// 声明enum类型
enum Gender {
  Mail = 0,
  Female = 1,
  Other = 2,
}
// 声明对象
let i: { name: string; gender: Gender };

i = { name: "xunwuxong", gender: Gender.Female };
console.log(i.gender === Gender.Female);
  1. 类型的别名,比如说这样使用
// 类型的别名
type myType = 1 | 2 | 3 | 4 | 5
let user: myType
let person: myType

user = 4
person = 1

2. 编译选项

2.1 自动编译文件

  1. 编译文件时,使用-w指令后,TS编译器会自动监视文件的变化,并在文件发送变化时对文件进行重新编译。
  2. 例如: tsc xxx.ts -w

2.2 自动编译整个项目

  • 如果直接使用tsc指令,则可以自动将当前项目下的所有ts文件编译为js文件(但是能直接使用tsc命令的前提是,需要在项目根目录下创建一个ts的配置文件tsconfig.json)
  • tsconfig.json是一个JSON文件,添加配置文件后,只需要tsc命令即可完成对整个项目的编译
  • 在tsconfig.json中的配置选项

2.2.1 include和exclude 配置项

1.include用来指定那些ts文件需要被编译

- * :匹配0或多个字符(表示任意文件)
- ** : 匹配任意子目录
- ? : 匹配一个任意字符

2. exclude用来指定那些ts文件不需要被编译

{
  "include": [
    "./src/**/*"
  ],
  "exclude": [ "node_modules", "**/*.spec.ts" ]
}

2.2.2 extends和files配置选项

  1. tsconfig.json文件可以利用extends属性从另一个配置文件里继承配置。
  2. files: 指定一个包含相对路径或绝对文件路径的列表。
"files": [ 
    "core.ts", 
    "sys.ts" 
    ],
 "extends": "./configs/base",
    
  • configs/base.json
{ 
    "compilerOptions": { 
        "noImplicitAny": true, 
        "strictNullChecks": true
    } 
}

2.2.3 compilerOptions配置选项

  1. 编译选项是配置文件中非常重要也比较复杂的配置选项
  2. compilerOptions中包含多个子选项,用来完成对编译的配置
  3. 编译选项
    1. target :指定ECMAScript目标版本,默认是ES3,可以设置"ES5", "ES6""ES2015", "ES2016", "ES2017"或 "ESNext"
    2. module : 指定生成那个模块系统代码。可以设置的值有"CommonJS", "AMD", "System", "UMD", "ES6", "ES2015", "ES2020", "ESNext", "None", "ES2022"
    3. lib : 编译过程中需要引入的库文件列表,如果lib没有指定默认注入的库的列表。默认注入的库为:
      1. 针对于--target ES5DOM,ES5,ScriptHost
      2. 针对于--target ES6DOM,ES6,DOM.Iterable,ScriptHost
    4. outdir : 重定向输出目录,编译后的.js文件存放目录
    5. outFile : 将输出文件合并为一个文件。
    6. allowJs : 允许编译JavaScript文件,默认为false,不允许编译.js文件
    7. checkJs : 在.js文件中报告错误。(检查js代码是否规范)与--allowJs配合使用
    8. removeComments : 删除所有注释。
    9. noEmit : 不生成输出文件
    10. noEimtOnError : 报错时不生成输出文件
{
  "compilerOptions": {
    "target": "ES6",
    "module": "AMD",
    "lib": ["es6", "DOM"],
    "outDir": "./dist",
    "allowJs": true,
    "checkJs": true,
    "removeComments": true,
    "noEmit": false,
    "noEmitOnError": true
  },
  "include": [
    "./src/**/*"
  ],
  "exclude": [
    "./src/hello/**/*"
  ]
}

2.3 语法检查

  1. 在.js文件的开头加入 "use strict",表示.js文件是用严格模式来检查语法
  2. tsconfig.json中compilerOptions配置
    1. alwaysStrict : 以严格模式解析并为每个源文件生成"use strict"语句
    2. noImplicitAny : 在表达式和声明上有隐含的any类型时报错。
    3. noImplicitThis : 当this表达式的值为any类型的时候,生成一个错误
    4. strict : 启用所有严格类型检查选项

3. 使用webpack打包ts代码

3.1 打包ts步骤

  1. 使用npm init对当前项目进行初始化
  2. 安装webpack所需的依赖
    1. npm install -D webpack@5.6.0
    2. npm install -D webpack-cli@4.2.0
    3. npm install -D typescript@4.1.2
    4. npm install -D ts-loader@8.0.11
  3. 在项目目录下新建文件夹src新建在 src下新建index.ts文件,项目根目录下新建webpack.config.js文件、tsconfig.json文件
    // src/index.ts
    function sum(a: number, b: number) {
      return a + b;
    }
    console.log(sum(2, 4));

    // tsconfig.json文件
    {
  "compilerOptions": {
    "target": "ES2015",
    "module": "ES2015",
    "strict": true
  },
  "include": [
      "src/*"
  ],
  "exclude": [
      "node_modules",
      "**/*.spec.ts"
  ]
}  
    // webpack打包配置文件 webpack.config.js
    const path = requier("path")
    module.export = {
        entry: "./src/index.ts",
        output:{
            path: path.resolve(__dirname,"dist"),
            filename: bundle.js
        },
        module: {
            rules: [
                test: /\.ts$/,
                use: 'ts-loader'
                exclude: /node_modules/
            ]
        }
    }
  1. 最后使用npm run xxx 命令打包ts代码

3.2 优化打包ts代码

  1. 安装html-webpack-plugin插件,自动生成html代码 npm install -D html-webpack-plugin@4.5.0
  2. 安装webpack-dev-server,用于配置自动启动浏览器实时打包代码 `npm install -D webpack-dev-server@3.11.0
  3. 安装clean-webapck-plugin插件,每次编译前把生成的dist目录文件清空 npm install -D clean-webpack-plugin@4.0.0
  4. 在webpack.config.js中配置resolve,设置引用模块
  5. 在webpack.config.js的配置文件
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
  entry: "./src/index.ts",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.js",
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: "ts-loader",
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [
    new htmlWebpackPlugin({
      title: "my app",
      filename: "index.html",
      template: "./src/index.html",
    }),
    new CleanWebpackPlugin(),
  ],
  // 用来设置引用模块
  resolve: {
    extensions: [".js", ".ts"],
  },
};

3.3 使用Babel,对旧浏览器做兼容性处理,支持es5以下的语法支持

  1. 需要安装的插件有 @babel/core@7.12.9 @babel/preset-env@7.12.7 babel-loader@8.2.2 core-js@3.8.0
npm install --save-dev @babel/core@7.12.9
npm install --save-dev @babel/preset-env@7.12.7
npm install babel-loader@8.2.2 --save-dev
npm install core-js@3.8.0 --save-dev
  1. 在webpack.config.js配置babel
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
  mode: "production",
  entry: "./src/index.ts",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.js",
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: [
          // 配置Babel
          {
            // 指定加载器
            loader: "babel-loader",
            // 设置babel
            options: {
              // 设置预定于的环境
              presets: [
                [
                  // 指定环境插件
                  "@babel/preset-env",
                  // 配置信息
                  {
                    targets: {
                      edge: "12",
                      firefox: "60",
                      chrome: "60",
                      safari: "11.1",
                      ie: "11",
                    },
                    // 使用corejs的方式, usage表示按需加载
                    useBuiltIns: "usage",
                    // 指定corejs的版本
                    corejs: "3",
                  },
                ],
              ],
            },
          },
          "ts-loader",
        ],
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [
    new htmlWebpackPlugin({
      title: "my app",
      filename: "index.html",
      template: "./src/index.html",
    }),
    new CleanWebpackPlugin(),
  ],
  // 用来设置引用模块
  resolve: {
    extensions: [".js", ".ts"],
  },
};