typeScript学习自用

typescript简介

  • 以JavaScript为基础构建的语言
  • 可以在任何支持JavaScript的平台中执行
  • 一个JavaScript的超集
  • TypeScript扩展了JavaScript,并添加了类型
  • TS不能被JS解析器直接执行
    在这里插入图片描述
    typeScript增加了
  • 支持ES的新特性
  • 类型
  • 添加ES不具备的新特性
  • 丰富的配置选项
  • 强大的开发工具

类型

// 字面量,相当于常量

 let a: 10;
 a = 10;
 a = 11;

// 可以使用|来连接多个类型

let b1: "male" | "female";
b1 = "male";
b1 = "female";

let c: boolean | string;
c = true;
c = "hello";

// any 表示的是任意类型,使用ts时不建议使用any类型,声明变量如果不指定类型,则ts解析器会自动判断变量的类型为

any(隐式的any)
let d: any;
d = "hello";
d = 10;
d = true;

// unknown 表示未知类型

let e: unknown;
e = 10;
e = "hello";
e = true

// unknown 实际上是一个类型安全的any
// unknown类型的变量不可以直接赋值给其他变量
// 赋值时需要先检查类型

let s: string;
// d的类型是any,他可以赋值给任意类型的变量
s = d;
// unknown 实际上是一个类型安全的any
// unknown类型的变量不可以直接赋值给其他变量
// 赋值时需要先检查类型
s = e;

if (typeof e === "string") {
  s = e;
}

// 类型断言,可以用来告诉解析器变量的实际类型

  • 语法:
    • 变量 as 类型
    • <类型>变量
s = e as string;

// void 用来表示空,就表示没有返回值

function fn(): void {

}

// never 表示永远不会有返回结果

function fn2(): never {
  throw new Error("报错了!!")
}

// object表示一个js对象

let a: object;
a = {}
a = function () {

}

// {} 用来指定对象中可以包含哪些属性
// 语法:{属性名:属性值,属性名:属性值}
// 在属性名后加上,表示属性是可选的

let b2: { name: string, age?: number }
b2 = {
  name: "haha", age: 12
}

//[propName:string]:any表示任意类型的属性

let c1: { name: string, [propName: string]: any };
c1 = {
  name: "aa", a: 1, b: 2
}

// 设置函数结构的类型声明

let d1: (a: number, b: number) => number;
d1 = function (n1, n2) {
  return n1 + n2
}
  • 数组的类型声明:
    • 类型[]
    • Array<类型>

// string[]表示字符串数组

let e1: string[];
e1 = ['x', 'c', 'v'];

// number[]表示数值数组

let f: number;
let g: Array<number>;
g = [1, 2, 3]

// 元组,元组就是固定长度的数组
// 语法:[类型,类型,类型]

let h: [string, number];
h = ['hello', 123];

// enum 枚举

enum Gender {
 Male = 0,
 female = 1
}
let i: { name: string, gener: Gender };
i = {
 name: 'zpp',
 gener: Gender.Male
}

// &表示同时

let j: { name: string } & { age: number };
j = { name: "zpp", age: 18 };

// 类型别名

type myType = 1 | 2 | 3 | 4 | 5;
let k: myType;
let l: myType;
k = 2;
  • 类型
类型例子描述
number1,-33任意数字
string‘a’,‘v’任意字符串
booleantrue,false布尔值true或false
字面量其本身限制变量的值就是该字面量的值
any*任意类型
unknown*类型安全的any
void空值(undefined)没有值(或undefined)
never没有值不能是任何值
object{name:“aa”}任意的js对象
array[1,2,3]任意的js数组
tuple[1,4]元组,ts新增类型,固定长度的数组
enumenum{A,B}枚举,ts中新增类型

编译

tsc app.ts -w //自动监视,在文件改变的时候进行编译

配置选项

tsconfig.json 是ts编译器的配置文件,ts编译器可以根据他的信息来对代码进行编译

  • include
    • 哪些ts文件需要被编译
    • 默认值["**/*"],**任意目录 *任意文件
    • 实例:
	 "include": ["./src/**/*" ],
  • “exclude”
    • 不需要被编译的文件目录
    • 默认值:[“node_modules”,“bower_components”,“jspm_packages”]
  • “extend”
    • 定义被继承的文件
  • "files”
    • 指定被编译文件的列表,只有需要编译的文件少是才会用到
    • 示例
"files":[
	"score.ts",
	"sys.ts",
	"type.ts"
]
  • “compilerOptions”
    • 编译选项
  "compilerOptions": {
    // target 用来指定ts被编译为的ES的版本
    // 'es3 ','es5','es6 ' , 'es2015', 'es2016 ' , 'es2017', 'es2018', 'es2019', 'es2020' , 'esnext'
    "target": "ES3",
    // module 指定要使用的模块化规范
    "module": "system",
    // lib用来指定项目中要是用的库
    // "lib": [],
    // outDir 用来指定编译后文件所在的目录
    "outDir": "./dist",
    // 将代码合并成一个文件
    // 设置motFile后,所有的全局作用域中的代码会合并到同一个文件中
    "outFile": "./dist/app.js",
    // 是否对js文件进行编译,默认所示false
    "allowJs":false,
    // 是否检查js代码是否符合语法规范,默认是false
    "checkJs":false,
    // 是否一处注释
    "removeComments":false,
    // 不生成编译后的文件
    "noEmit":false,
    // 当有错误时不生成编译后的文件
    "noEmitOnError":true,

    // 所有严格检查的【总开关】 以下4个都会打开 
    "strict":true,

    // 用来设置编译后的文件是否使用严格模式,默认false
    "alwaysStrict":true,
    // 不允许隐式的any类型
    "noImplicitAny":true,
    // 不允许不明确类型的this
    "noImplicitThis":true,
    // 严格的检查空值
    "strictNullChecks":true,
  }

使用webpack打包ts代码

  1. 初始化项目
    在项目中使用npm init -y命令生成package.json文件
  2. 下载构建工具
cnpm i -D webpack webpack-cli typescript ts-loader
  1. 配置webpack.config.js文件
const path = require('path')
// 
module.exports = {
  // 指定入口文件
  entry: "./src/index.ts",
  // 指定打包文件所在的文件
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename:"bundle.js"
  },
  // 指定webpack打包时要用的模块
  module: {
    // 指定要加载的规则
    rules: [
      {
        // test指定的是规则生效的文件
        test: /\.ts$/,
        // 要是用的loader
        use: 'ts-loader',
        // 指定要排除的文件
        exclude:/node_modules/
      }
    ]
  }
}
  1. 配置tsconfig.json文件
{
  "compilerOptions": {
    "module": "ES2015",
    "target": "ES2015",
    "strict": true
  }
}
  1. 修改package.json
    在这里插入图片描述
  2. 使用npm run build 进行打包
  3. 自动生成HTML

安装

cnpm i -D html-webpack-plugin

引入

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

配置webpack插件

  // 配置webpack插件
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html"
    }),
  ]
npm run build
  1. 自动打开实时更新网页

安装

cnpm i -D webpack-dev-server

在package.json中配置

"start": "webpack serve --open chrome.exe"
npm start
  1. 清除之前生成的打包文件

安装

cnpm i -D clean-webpack-plugin

引入

const { CleanWebpackPlugin } = require("clean-webpack-plugin")

配置webpack插件

new CleanWebpackPlugin(),
  1. 配置引入模块
    在webpack.config,js中配置
 // 用来设置引用模块
  resolve: {
    extensions: ['.ts', '.js']
  }
  1. 其他配置

安装

cnpm i -D @babel/core @babel/preset-env babel-loader core-js
  // 指定要加载的规则
    rules: [
      {
        // test指定的是规则生效的文件
        test: /\.ts$/,
        // 要是用的loader
        use: [
          {
            // 指定加载器
            loader: 'babel-loader',
            // 设置babel
            options: {
              //设置预定义的环境
              presets: [
                [
                  // 指定环境的插件
                  "@babel/preset-env",
                  //配置信息
                  {
                    // 要兼容的目标浏览器
                    targets: {
                      "chrome": "58",
                      "ie": "11"
                    },
                    // 指定corejs的版本
                    "corejs": "3",
                    // 使用corejs的方式
                    "useBuiltIns": "usage"

                  }
                ]
              ]
            }
          },
          'ts-loader'
        ],

不使用箭头函数

  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: "bundle.js",
    // 告诉webpack不能使用箭头
    environment: {
      arrowFunction: false
    }
  },

面向对象

类的简介
  • 直接定义的属性是实例属性,需要通过对象的实例去访问:
    const per = new Person();
    per.name

  • 使用static开头的属性是静态属性,可以直接通过类对访 问
    Person.age

  • readonly开头的属性表示一个只读的属性无法修改

// 使用class关键字来定义一个类
class Person {
  // 定义实例属性
  name: string = "zpp";
  // age: number = 18;
  // 在属性前使用static关键字可以定义类属性(静态属性)
  // static age: number = 18;
  static readonly age: number = 18
  // 定义方法
  // 如果方法以static开头则是类方法,不实例就可以使用
  sayHello() {
    console.log("Hello")
  }
}
const per = new Person();
console.log(per)
console.log(Person.age)
构造函数
class Dog {
  name: string;
  age: number;
  // constructor 被称为构造函数
  // 构造函数会在对象创建时调用
  constructor(name: string, age: number) {
    // 在实例方法中,this就表示当前的实例
    // 在构造函数中当前对象就是当前新建的那个对象
    // 可以通过this向新建的对象中添加属性
    this.name = name;
    this.age = age
    console.log(this);
  }
  bark() {
    alert("汪汪汪")
    // 在方法中可以通过this来表示当前调用方法的对象
    console.log(this.name)
  }
}
const dog = new Dog("xiaog", 12)
console.log(dog)
继承
  // 定义一个Animal类
  class Animal {
    name: string;
    age: number;
    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }
    sayHello() {
      console.log("动物叫")
    }
  }
  /**
   * - 此时,Animal被称为父类,Dog被称为子类
     - 使用继承后,子类将会拥有父类所有的方法和属性
     - 通过继承可以将多个类中公有的代码卸载一个父类照片那个
        这样只需要写一次即可让所以的子类都同时拥有父类的属性
        如果希望在子类中添加一些父类中没有的属性或方法直接加就可以
     - 如果在子类中添加了和父类相同的方法,则子类方法会覆盖掉父方法
        这种子类覆盖掉父类方法的形式,我们称为方法重写

   */
  class Dog extends Animal {


  }
  class Cat extends Animal {
    sayHello() {
      console.log("miao")
    }

  }
  const dog = new Dog("wang", 5)
  dog.sayHello();
  const cat = new Cat("miao", 3)
  cat.sayHello()
super

super 表示当前类的父类,如果在子类中写了构造函数,在子类的构造函数中必须调用父类的构造函数

抽象
  abstract class Animal {
    name: string;
    constructor(name: string) {
      this.name = name;
    }
    // 定义一个抽象方法
    // 抽象方法使用abstract开头,没有方法体
    // 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
    abstract sayHello(): void
  }
  class Dog extends Animal {
    sayHello() {
      console.log("wang")
    }
  }
接口
  // 描述一个对象的类型
  type myType = {
    name: string,
    age: number,
    // [propname: string]: any
  }
  const obj: myType = {
    name: 'sss',
    age: 111
  }

  // 接口用来定义一个类的结构,用来定义一个类中应该包含哪些属性和方法
  // 同时接口可以当成类型声明去使用
  interface myInterface {
    name: string;
    age: number;
  }
  interface myInterface{
    gender: string;
  }
  const obj1: myInterface = {
    name: 'sss',
    age: 111,
    gender:"male"
  }
  
  // 接口可以在定义类的时候去现在类的结构
  //  接口中的所有属性都不能有实际的值
  //  接口只能定义对象的结构,而不考虑实际值
  //  在接口中所有的方法都是抽象方法
  interface myINter {
    name: string;
    sayHello(): void;
  }
  /**
   * 定义类时,可以使类去实现一个接口,
   * 实现接口就是满足接口的需求
   *  */
  class myClass implements myINter {
    name: string;
    constructor(name: string) {
      this.name = name
    }
    sayHello(): void {
      throw new Error("Method not implemented.")
    }
  }
属性的封装

public 修饰的属性可以在任意位置访问(修改)默认值
private 私有属性,私有属性只能在类内部进行访问(修改)

  class Person {
    private _name: string;
    private _age: number;
    constructor(name: string, age: number) {
      this._name = name;
      this._age = age;
    }
    // getter 用来读取属性
    // setter 方法用来设置属性
    get name() {
      return this._name;
    }
    get age() {
      return this._age;
    }
    set name(value) {
      this._name = value;
    }
    set age(value) {
      if (value >= 0) {
        this._age = value;
      }
    }
  }

  const per = new Person('zpp', 18);
  console.log(per)
  console.log(per.name)
  per.name = "1234"
  console.log(per.name)

protexted 受保护的属性,只能在当前类的子类中访问(修改)

  class A {
    protected num: number;
    constructor(num:number) {
      this.num =num
    }
  }
  class B extends A {
    test() {
     console.log(this.num)
   }
  }

简单写法,语法糖

class C {
    constructor(public name: string, public age: number) {

    }
  }
  const c = new C("xxx", 12)
  console.log(c)
泛型
(function () {
  // 在定义函数或是类时,如果遇到类型不明确就可以使用泛型
  function fn<T>(a: T): T {
    return a;
  }
  let result = fn(10); // 不指定泛型,TS可以自动对类型进行推断
  let result1 = fn<string>("123"); // 指定泛型


  //泛型可以同时指定多个
  function fn2<T, K>(a: T, b: K): T {
    return a;
  }
  fn2<number, string>(13, "zpp");


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

  class MyClass<T> {
    name: T;
    constructor(name: T) {
      this.name = name;
    }
  }
  const mc = new MyClass<string>('zpp')
})()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值