别人的Ts

87 阅读6分钟

TypeScript

TypeScript是什么

  1. 以JavaScript为基础构建的语言
  2. 一个JavaScript的超集
  3. 可以在任何支持JavaScript的平台中执行 (TS不能被JS解析器直接执行)
  4. TypeScript扩展了JavaScript,并添加了类型

TypeScript增加了什么

  1. 类型
  2. 支持ES的新特性
  3. 添加ES不具备的新特性
  4. 丰富的配置选项
  5. 强大的开发工具

TypeScript开发环境搭建

  1. 下载Node.js
  2. 安装Node.js
  3. 使用npm全局安装typescript npm i -g typescript
  4. 创建一个ts文件
  5. 使用tsc对ts文件进行编译
    1. 进入命令行
    2. 进入ts文件所在目录
    3. 执行命令:tsc xxx.ts

TS的类型声明

基本类型

  1. 类型声明

    1. 类型声明式TS非常重要的一个特点

    2. 通过类型声明可以指定TS中变量(参数,形参)的类型

    3. 指定类型后,当为变量赋值时,TS编译器会自动检查值是否符合类型声明,符合则赋值,否则会报错

    4. 简而言之,类型声明给变量设置了类型,使得变量只能存储某种类型的值

    5. 语法

      let 变量:类型
      let 变量:类型 = 值
      function fn(参数:类型,参数:类型):类型 {
          ...
      }
      
  2. 自动类型判断

    1. TS拥有自动的类型判断机制
    2. 当对变量的声明和赋值是同时进行的,TS编译器会自动判断变量的类型
    3. 所以如果你的变量的声明和赋值是同时进行的,可以省略掉类型声明
  3. 类型

类型例子描述
number1,-33,2.5任意数字
string"hi"任意字符串
booleantrue false布尔值true或false
字面量其本身限制变量的值就是该字面量的值
any*任意类型
unknown*类型安全的any
void空值(undefined)没有值(或undefined)
never没有值不能是任何值
object{name:"孙悟空"}任意的JS对象
array[1,2,3]任意的JS数组
tuple[4,5]元素,TS新增类型,固定长度数组
enumenum{A,B}枚举,TS中新增类型
number
let decimal:number = 6
let hex:number = 0xf00d
let binary:number = 0o744
let big:bigint = 100n
boolean
let isDone:boolean = false
string
let color:string = 'blur'
color = 'red'

let fullName:string = `Bob Bobbington`
let age:number = 37
let sentence:string = `Hello,my name is ${fullName}`
字面量
// 也可以使用字面量去指定变量的类型,通过字面量可以确定变量的取值范围
let color: 'red' | 'blue' | 'black'
let num: 1 | 2 | 3
any
let d:any = 4
d = 'hello'
d = true
unknown
let notSure:unknown = 4
notSure = 'hello'
void
function fn(message:string):void {
    xxx
}
let unusable:void = undefined
never
function error(message:string):never {
    throw new Error(message)
}
object(没什么用)
let obj:object = {}
array
let array:number[] = [1,2]
let array: Array<number> = [1,2]
tuple
let x :[string,number]
x = ['hello',10]
enum
enum Color {
    Red,
    Green,
    Blue
}
let c:Color = Color.Green

enum Color {
    Red = 1,
    Green,
    Blue
}
let c:Color = Color.Green

enum Color {
    Red = 1,
    Green = 2,
    Blue = 4
}
let c:Color = Color.Green

类型断言

有些情况下,变量的类型对于我们来说是很明确,但是TS编译器却并不清楚,此时,可以通过类型断言来告诉编译器变量的类型,断言有两种形式:

第一种

let someValue :unknown = 'this is a string'
let strLength:number = (someValue as string).length

第二种

let someValue :unknown = 'this is a string'
let strLength:number = (<string>someValue).length

TS编译选项

自动编译文件

编译文件时, 使用-w 指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件进行重新编译

示例

tsc xxx.ts -w

自动编译整个项目

  1. 如果直接使用tsc指令,则可以自动将当前项目下的所有ts文件编译为js文件

  2. 但是能直接使用tsc命令的前提时,要先在项目根目录下创建一个ts的配置tsconfig.json

  3. tsconfig.json是一个JSON文件,添加配置文件后,只需tsc命令即可完成对整个项目的编译

  4. 配置选项

    1. include

      1. 定义希望被编译文件所在目录
      2. 默认值:["* * /*"]
      3. 示例
      // 上述示例中,所有src目录和tests目录下的文件都会被编译 **表示任意目录 *表示任意文件
      "include":["src/**/*","tests/**/*"]
      
    2. exclude

      1. 定义需要排除在外的目录

      2. 默认值["node_modules","bower_components","jspm_packages"]

      3. 示例

        "exclude":["./src/hello/**/*"]
        

        上述示例中,src下hello目录下的文件都不会被编译

    3. extends

      1. 定义被继承的配置文件

      2. 示例

        "extends":"./configs/base"
        

        上述示例中,当前配置文件中会自动包含config目录下base.json中的所有配置信息

    4. files

      1. 指定被编译文件的列表,只有 需要编译的文件少时才会用到

      2. 示例

        // 列表中的文件都会被TS编译器所编译
        "files":[
            "core.ts",
            "sys.ts",
            "types.ts",
            "scanner.ts",
        ]
        
    5. compilerOption

      1. 编译选项是配置文件中非常重要也比较复杂的配置选项

      2. 在compilerOptions中包含多个子选项,用来完成对编译的配置

        "compilerOptions":{
            // target 用来指定ts被编译为的ES版本 
            // es3 es5 es6 es2015 es2016 es2017 es2018 es2109 es2020 esnext
            "target":"es2015",
            // module 指定要使用模块化的规范
            // 'none''commonjs''amd''system''umd''es6' 'es2015' 'es2109' 'es2020'
            "module":"es2015",
            // lib用来指定项目中要使用的库 一般默认值  到Node 根据实际在改
            "lib":["dom"],
            // outDir 用来指定编译文件所在的目录
            "outDir":'./dist',
            // outFile 将代码合并为一个文件  设置outFile后,所有的全局作用域中的代码会合并到同一个文件 要注意模块化
            "outFile":"./dist/app.js",
            // 是否对js文件进行编译,默认是false
            "allowJs":false,
            // 是否检查JS 符合语法规范,默认是false
            "checkJs":false,
            // 是否移除注释
            "removeComments":false,
            // 不生成编译后的文件
            "noEmit":false,
            // 当有错误时不生成编译后的文件
            "noEmitOnError":true,
            
            // 所有的严格检查的总开关
            "strict":true,
            // 用来设置编译后的文件是否使用严格模式,默认false
            "alwaysStrict":false,
            // 是否允许隐式的any
            "noImplicitAny": false,
            // 是否允许隐式的this
            "noImplicitThis":false,
            // 严格的检查空值
            "strictNullChecks":false,
            
        }
        

使用webpack打包ts代码

  1. 安装依赖

    1. npm i -D ts-loader typescript webpack webpack-cli webpack-dev-server @babel/core @babel/preset-env babel-loader clean-webpack-plugin core-js html-webpack-plugin

    2. 创建tsconfig.json webpack.config.js 文件

      // webpack.config.js 
      
      // 引入一个包
      const path = require('path')
      
      // 引入html插件
      const HTMLWebpackPlugin = require("html-webpack-plugin")
      
      // 引入clean插件
      const {CleanWebpackPlugin} = require('clean-webpack-plugin')
      
      //webpack中的所有的配置信息都应该写在module.exports中
      module.exports = {
          // 指定入口文件
          entry:"./src/index.ts",
          // 指定打包文件所在的目录
          output:{
              // 指定打包文件的目录
              path:path.resolve(__dirname,'dist'),
              // 打包后文件的文件
              filename: "bundle.js",
              // 告诉webpack 不使用箭头
              environment:{
                  arrowFunction: false
              }
          },
      
          // 指定webpack打包时要使用模块
          module:{
              // 指定要加载的规则
              rules:[
                  {   
                      // test指定的是规则生效的文件
                      test:/\.ts$/,
                      // 要使用的loader
                      use:[
                          // 配置babel
                          {
                              //指定加载器
                              loader:"babel-loader",
                              // 设置babel
                              options:{
                                  // 设置预定义的环境
                                  presets:[
                                      [
                                          // 指定环境的插件
                                          "@babel/preset-env",
                                          //配置信息
                                          {
                                              // 要兼容的目标浏览器
                                              targets:{
                                                  "chrome":"58",
                                                  "ie":"11"
                                              },
                                              // 指定corejs的版本
                                              "corejs":"3",
                                              // 使用corejs的方式"usage" 表示按需加载
                                              "useBuiltIns":"usage"
                                          }
                                      ]
                                  ]
                              }
                          },
                          "ts-loader"],
                      // 要排除的文件
                      exclude: /node-module/
                  }
              ],
          },
      
          // 配置webpack插件
          plugins:[
              // 每次清除dist
              new CleanWebpackPlugin(),
              new HTMLWebpackPlugin({
                  //title:"这是一个自定义的title"
                  template:"./src/index.html"
              }),
          ],
          // 用来设置引用模块
          resolve:{
              extensions:['.ts','.js']
          }
      }
      
      tsconfig.json
      {
          "compilerOptions":{
              "target":"es2015",
              "module":"es2015",
              "strict":true 
          }
      }
      
      package.json
      {
        "name": "part3",
        "version": "1.0.0",
        "description": "",
        "main": "index.js",
        "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1",
          "build": "webpack",
          "start": "webpack serve --open --mode=development"
        },
        "author": "",
        "license": "ISC",
        "devDependencies": {
          "@babel/core": "^7.16.0",
          "@babel/preset-env": "^7.16.4",
          "babel-loader": "^8.2.3",
          "clean-webpack-plugin": "^4.0.0",
          "core-js": "^3.19.3",
          "html-webpack-plugin": "^5.5.0",
          "ts-loader": "^9.2.6",
          "typescript": "^4.5.3",
          "webpack": "^5.65.0",
          "webpack-cli": "^4.9.1",
          "webpack-dev-server": "^4.6.0"
        },
        "dependencies": {}
      }
      

面向对象

面向对象是程序中一个非常重要的思想,面向对象,简而言之就是程序之中所有的操作都要通过对象来完成。

举例来说:

​ 操作浏览器要使用window对象

​ 操作网页要使用document对象

​ 操作控制台要使用console对象

一切操作都要通过对象,也就是所谓的面向对象,那么对象到底是什么呢?这就要先说到程序是什么,计算机程序的本质就是对现实事物的抽象,抽象的反义词是具体,比如:照片是对一个具体的人的抽象,汽车模型是对具体汽车的抽象等等。程序也是对事物的抽象,在程序中我们可以表示一个人,一条狗等等所有的事物。一个事物到了程序中就变成了一个对象。

在程序中所有的对象都被分成了两个部分数据和功能,以人为例,人的姓名、性别、年龄、身高、体重等属于数据,人可以说话、走路、吃饭、睡觉属于人的功能。数据在对象中被称为属性,而功能被称为方法,简而言之,在程序中一切皆是对象

class 类名 {
    属性名:类型
    constructor(参数:类型) {
        this.属性名 = 参数
    }
    方法名() {}
}
class Person {
    static readonly name:string   //静态 只读
    age:number
    constructor(name:string,age:number) {
        this.name = name
        this.age = age
    }
    sayHello() {
        console.log(213)
    }
}

// 简写方式
class Person {
    constructor(public name:string, public age:number) {}
    sayHello() {
        console.log(213)
    }
}

接口

// 描述一个对象的类型  type 不可以重复定义                                           
type myType = {
    name:string,
    age:number
}

// 接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法
// 同时接口也可以当成类型声明去使用  
// 接口是所有同名的合并
interface myInterface {
    name:string;
    age:number
}
interface myInterface {
    gender:string
}

/*
 接口可以在定义类的时候去限制类的结构
 接口中的所有属性都不能有实际的值
 接口只定义对象的结构,而不是考虑实际值
 在接口中所有的方法都是抽象方法
 */
interface myInter {
    name: string
    sayHello() :void
}
/*
	定义类时,可以使类去实现一个接口
	实现接口就是使类满足接口的要求
*/
class Myclass implements myInter {
    name:string
    constructor(name:string) {
        this.name = name
    }
     sayHello() :void {
         console.log("hello world")
     }
}

属性的封装

class Person {
    /*
    	public 修饰的属性可以在任意位置访问(修改)默认值
    	private 私有属性,私有属性只能在类内部进行访问(修改)
    		通过类中添加方法使得私有属性可以被外部访问
    	protected 受包含的属性,只能在当前类和继承类访问
    */
    private name:string
    age:number
    constructor(name:string,age:number) {
        this.name = name
        this.age = age
    }
    // 定义方法,用来获取name属性
    getName() {
        return  this.name
    }
    // 定义方法,用来设置name
    setName(name:string) {
        this.name = name
    }
    
    /*
    	getter 用来读取属性
    	setter 用来设置属性
    		他们被称为属性的存取器
    */
    get age() {
        return this.age
    }
    set age(value:number) {
        this.age = value
    }
}
const per = new Person("孙悟空",18)
/*
	现在属性是在对象中设置的,属性可以任意的被修改
	属性可以任意被修改将会导致对象中的数据变得非常不安全
*/

泛型

// 在定义函数或是类时,如果遇到类型不明确就可以使用泛型
function fn<T>(a:T):T {
    return a
}

// 可以直接调用具有泛型的函数
fn(10)   // 不指定泛型,TS可以自动对类型进行推断 但不一定能推断出来
fn<string>("hello")  // 指定泛型

// 泛型可以同时指定多个
function fn2<T,K> (a:T,b:K):T {
    console.log(b)
    return a
}
fn2<number,string>(2,"hello world")

interface Inter {
    length:number;
}
// T extends Inter 表示泛型T必须实现Inter实现类(子类)
function fn3<T extends Inter>(a:T):number {
    return a.length
}
fn3({length:10})

class MyClass<T> {
    name:T
    construcctor(name:T) {
        this.name = name
    }
}
const xx = new MyClass<string>("sunwukong")