首页 > 其他 > 详细

TypeScript基础

时间:2021-04-26 22:48:43      阅读:31      评论:0      收藏:0      [点我收藏+]

TypeScript

JavaScript的超集, 拓展了JavaScript,并添加了类型

可以在任何支持Javascript的平台中执行,不能被js解析器直接执行, 需要编译转换(类比less, scss)

环境搭建

  1. 下载并安装node.js
  2. npm i -g typescript全局安装ts编译器
  3. 写ts文件,
  4. 在文件目录下运行tsc xxx.ts

类型声明

  1. 声明并定义类型
  2. 赋值时自动定义类型
  3. 函数的参数和返回值定义类型
let a: number // 声明一个变量, 并指定它的类型为number
a = 10
a = ‘hello‘ // 会有红线提示,不能将类型“string”分配给类型“number”。

// 声明并定义
let b : number = 1
b = true

// 实际上声明和赋值是同时进行的, ts可以自动对变量进行类型检测
let c = true
c = 1

// 为什么还要主动定义呢? 主要是函数的参数和返回类型
function sum (a: number, b: number): number{	// 括号后面的冒号表示返回的类型
  return a + b
}

sum(123, ‘456‘)   // 第二个类型不符合会报错

sum(123, 456, 789)  // 如果是js, 多传参并不会报错, 但js更严格, 不允许多传参

// 虽然报错了, 但还是会编译成js, 只是会在编译时报错, 如果想报错不编译, 需要配置

ts中的类型

  1. number
  2. string
  3. boolean
  4. 字面量
// 也可以用字面量进行类型声明
let gender : ‘man‘ | ‘woman‘ | 0 | 1
gender = ‘man‘
gender = 0
gender = ‘女‘  // 限定变量在某几个值之间

let d : string | number
d = true
  1. any : 任意类型, 对该变量关闭ts检测(尽量不用)

    // 1显式声明
    let e: any
    e = 10
    e = true
    
    // 2. 隐式声明
    let f // 声明变量如果不赋值, ts解析器就会自动当成any
    f = 10
    f = true
    
  2. unkonwn: 未知类型

    和any有什么区别:

    ? any可以赋值给任意变量(不仅影响自己, 还影响别人 )

    ? unknow不能直接赋值给其他变量

    ? unknow实际上就是一个类型安全 的any,

    let s1 : any
    s1 = 123
    let s2 : string
    s2 = s1  // any可以赋值给任意变量, 这里不会报错
    
    let s3 : unknown
    s3 = 123
    let s4 : string
    s4 = s3  // unknow会报错
    
    // unkown要怎么赋值给其他变量呢
    // 方法1:先做类型判断
    if(typeof s3 === ‘string‘){
      s4 = s3
    }
    
    // 方法2: 类型断言, 用来告诉解析器变量的实际类型
    /*
     * 语法: 变量 as 类型
     *      <类型> 变量
     **/
    s4 = s3 as string
    s4 = <string>s3
    
  3. void: 为空, 主要用在函数的返回值, 没有返回值

  4. never: 永远不会返回结果, 连undefind都不返回, 比如用来捕获异常的函数, 直接就抛出了

  5. object

    let a:object  //并不这么用, 因为js里数组对象函数都是对象
    a = {}
    a = function () {}
    
    let b : {name:string, age?:number, [propName:string]:any}
    // 一般指定对象包含的属性
    // 语法: {属性名: 属性值类型, ...}
    // 属性名后面的问号表示是可选的
    // [propName:string]:any 表示任意类型的属性, 就是说后面不做限制, 可以有多个属性, 属性值类型任意
    b = {}
    b = {name : ‘abc‘}
    
    // 定义函数的类型声明
    // 类似箭头函数的结构
    // 语法: (形参:类型, 形参:类型,...)=> 返回值类型
    let c : (a: number, b:number)=>number
    
  6. array

    // 用来表示数组里存放什么类型的数据
    let a : string[]
    let b : <number>[]
    
  7. tuple: ts新增的类型, 元组, 固定长度的数组

    let a : [string , string]  // 长度固定, 效率更好
    a = [‘hello‘, ‘word‘]
    
  8. enum: ts新增的类型, 枚举

    enum Gender {
        woman = 0,
        man = 1
    }
    
    let g : {name:string, gender:Gender}
    
    g = {
        name: ‘张三‘,
        gender:Gender.man
    }
    
    console.log(g.gender === Gender.man)
    // 把可能出现的列出来
    
  • |表示或, &表示且

    let j : {name: string} & {age: number}
    j = {name: ‘张三‘, age: 18}
    
  • 类型的别名

    type myType = 1 | 2 | 3 | 4 | 5
    let a : myType
    let b : myType
    

编译配置

  • 自动编译

    • 监控单个文件 tsc xxx.ts -w*

    • 监控整个项目

      1. 要有相关配置文件tsconfig.json, 可以用tsc -- init生成

      2. 配置文件里只要一对大括号, 就能生效

      3. tsc

  • 配置选项

    • include: 定义希望被编译文件所在的目录

      "include": [
          "./src/**/*"
      ]
      // 两个星号表示任意目录, 一个星号表示任意文件
      
    • exclude: 排除目录

    • extends: 继承的配置文件

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

    • compilerOptions: 编译器的选项 (技巧, 写个错的, 报错信息会显示哪些可选项)

      • "target": "es2015" es版本

      • "module": "es2015" 使用的模块化规范

      • // "lib":[] 项目使用的库, 一般不改

      • "outDir": "./dist" 编译后输出的目录

      • "outFile": "./dist/app.js" 将全局作用域的代码合并到一个文件

      • "allowJs": false 是否对js文件进行编译, 默认false

      • "checkJs": false 检查js是否符合规范 , 默认是false

      • "removeComments": false 是否移除注释

      • "noEmit": false 只检查语法, 不生成编译后的文件

      • "noEmitOnError": false 有错误时不生成编译后的文件

      • "strict": true 所有的严格检查开关, 建议打开

      • "alwaysStrict": false 编译后的文件是否使用js严格模式

        当使用import, export时, 自动进入严格模式 , js中不会再生成"use strict"

      • "noImplicitAny": true 不允许隐式any类型

      • "noImpliciThis": true 不允许不明确类型的this,

        function fn1(){
            console.log(this)	//这里的this是不明确的, 不能确定谁会调用它
        }
        
        // 如果只想让能明确的对象来调用它, 怎么解决
        function fn1(this: window){
            console.log(this)
        }
        
        
      • "strictNullChecks": true 严格的检查空值

        let box = documnet.getElementById(‘box‘)
        box.addEventListener(type: ‘click‘, listener: function(){
            alert(‘hello‘)
        })
        // 这里的box可能拿不到, 后面的绑定事件就会出错
        // 配置了严格检查空值, 这里就会有提示
        
        // 怎么解决
        let box = documnet.getElementById(‘box‘)
        if(box !== null){
                box.addEventListener(type: ‘click‘, listener: function(){
                alert(‘hello‘)
            })
        }
        
        // 另一种写法
        box?.addEventListener(type: ‘click‘, listener: function(){
            alert(‘hello‘)
        })
        

结合webpack

  1. npm init -y 生成package.json

  2. npm i -D webpack webpack-cli typescript ts-loader 安装包

  3. 新建webpack.config.js

    const path = require(‘path‘)
    
    // webpack中的所有信息都写在这里
    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/
               }
           ]
       }
    }
    
  4. 新建tsconfig.json

    {
        // 随便配置下
        "compilerOptions": {
            "module": "ES2015",
            "target": "ES2015",
            "strict": true
        }
    }
    
  5. package.json新增

    {
        // ...
        "scripts": {
            // ...      
            ,
            "build": "webpack"
        }
        // ...
    }
    
  6. 执行npm run build 进行打包

其他webpack知识点补充:

  • 自动输出html文件

    1. 安装插件, npm i -D html-webpack-plugin

    2. src下新建index.html模板

    3. 配置webpack.config.js文件

// ...
const htmlWebpackPlugin = require(‘html-webpack-plugin‘)
//...
module.exports = {
    //...
	// webpack插件配置
    plugins: [
        new htmlWebpackPlugin(
            {
                template: "./src/index.html"
            }
        )
    ] 
}
  • 监控变化并重新生成

    1. 安装插件, npm i -D webpack-dev-server

    2. 配置package.json

      // ...
       "scripts": {
          // ...
           ,
          "start": "webpack serve --open chrome.exe"
      }
      // ...
      
    3. 运行npm run start

  • 每次打包前先清空dist目录

    1. 安装插件npm i -D clean-webpack-plugin

    2. 配置webpack.config.js文件

    // ...
    const {cleanWebpackPlugin} = require(‘clean-webpack-plugin‘)
    //...
    module.exports = {
        //...
        // webpack插件配置
        plugins: [
            new cleanWebpackPlugin(),
            new htmlWebpackPlugin(
                {
                    template: "./src/index.html"
                }
            )
        ] 
    }
    
  • 设置哪些文件可以当成模块来引用

    配置webpack.config.js文件

    ?```js
    // ...
    module.exports = {
      // 设置引用模块
      resolve: {
        extensions:[‘.ts‘, ‘.js‘]  // 这样设置后, ts里就可以引用ts
    }
    }
    ?```
    
  • 打包后的js的语法兼容: 使用babel , 结合webpack一起使用

    1. 安装依赖 npm i -D @babel/core @babel/preset-env babel-loader core-js

    2. 配置webpack.config.js文件

       module: {
           // 指定要加载的规则
           rules: [
               {
                   // test指定的是规则生效的文件
                   test: /\.ts$/,
                   // 使用loader, 这里要注意: loader的执行顺序是从下往上的
                   use: [
                     // 配置babel
                    { 
                      // 指定加载器
                      loader: ‘babel-loader‘,
                      // 配置项
                      options: {
                        // 设置预定义环境
                        presets:[
                          [
                            // 指定环境的插件
                            "@babel/preset-env",
                            // 配置信息
                            {
                              // 要兼容的浏览器
                              targets: {
                                "chrome": "58",
                                  "ie": "11"  // 设置了兼容ie,es6就转成旧写法了
                              },
                              // 指定corejs的版本
                              "corejs":"3",
                              // 使用corejs的方式, usage按需加载
                              "useBuiltIns": "usage"
                            }
                          ]
                        ]
                      }
                    },
                    ‘ts-loader‘
                   ],
                   // 排除的文件
                   exclude: /node-modules/
               }
           ]
       },
    
  • webpack打包不使用箭头函数(兼容ie)

    // ...
    output: {
        //...
        environment: {
            // 告诉webpack不使用箭头函数
            arrowFunction: false
          }
    }
    //...
    

面向对象

关键字class

构造函数construtor

继承extends

属性的重写 + 方法的重写 , super的使用

上面的都和js一样, 下面的抽象类和接口是ts独有的, 编译成js就没了

抽象类: abstrat

父类不想被实例

  // 抽象类: 不能用来创建对象, 就是专门用来被继承的父类
  // 在class前面加上abstrat
 abstract class Animal {
    name:string
    age:number
  
    constructor(name:string, age:number){
      this.name = name
      this.age = age
      
    }
    
    // 抽象方法: 定义在抽象类中, 只是表示了有这个方法, 必须在子类中进行重写
    //在方法名前加 abstract , 没有方法体
    abstract say():void
  }
  
    class Dog extends Animal {}

接口: interface

对类的结构做限制, 但不设置具体值

(function (){
  // 定义一个对象的类型
  type myType = {
    name: string,
    age: number
  }

  const obj:myType = {
    name: ‘张三‘,
    age: 18
  }

  /**
   * 接口就是用来定义一个类的结构, 应该包含那些属性和方法
   * 接口就是对类的限制
   *      也可以当成类型声明使用
   */

   // 1. 当成类型生明使用
  interface myInterFace{
    name: string
    age: number
  }

  interface myInterFace{
    height: number
  }
  //再定义一个同样名字的接口, 在ts里是合法的, 实际是两个合并

  const obj2: myInterFace = {
    name: ‘李四‘,
    age: 19,
    height: 180
  }

  // 2. 定义类的结构
  // 接口中的属性都不能有实际的值
  // 接口只是定义了对象的结构,而不考虑实际值
  interface myInter {
    name:string
    say():void // 接口中的方法都时抽象方法
  }

  // 类实现接口, 用implements
  class myClass implements myInter{
    name: string
    constructor(name: string){
      this.name = name
    }
    say (){
      console.log(‘123‘);
    }
  }
  const myclass = new myClass(‘王五‘)
  console.log(myclass.name);
  myclass.say()
})()

属性的封装: private

如果不想让属性被任意修改, 可以添加private 设置私有属性, 类内部添加get, set存取器修改

// 实例属性在实例中是可以被任意修改的, 如果不想被修改? 或者要按照我的方法来修改
// 添加private 设置私有属性, 类内部添加修改方法
// tsconfig.json 中添加 "noEmitOnError":true, 错误时不编译
(function(){
  class Person{
    /**
     * TS可以在属性前面添加修饰符, 比如之前的static
     * public 表示公共属性, 默认添加
     * private 表示私有属性, 只能在类内部访问(修改)
     * protected 表示受保护的类, 只能在当前类和当前类的子类中访问
     * 可以通过类内部的方法间接修改
     */
    private _name:string
    private _age: number

    constructor(name:string, age:number){
      this._name = name
      this._age = age
    }

    setName(value:string){
      this._name = value
    }

    setAge(value: number){
      if(value > 0 && value <150){
        // 在内部的方法添加了限制, 只有符合设置规则的修改才允许
        this._age = value
      }
    }

    /**
     * getter方法用来读取属性, setter方法用来设置属性, 它们被称为属性的存取器
     * TS中提供了更方便写法 set get
     * 用的时候当成属性来用
     */
    get name():string{
      return this._name  // get访问器不能有参数, 必须用return返回
    }

    set name(value:string){
      this._name = value   // set访问器必须有参数, 不能有return
    }
  }

  const per = new Person("张三", 18)
  console.log(per);
  //per._name = "李四"  // 报错了, 私有属性只能在类内部修改

  per.setName(‘李四‘)
  console.log(per)

  per.setAge(-1)  // 不符合规则, 不让修改
  console.log(per)
  
  console.log(per.name); // 直接调用了set访问器
  per.name = "王五"   // set访问器, 和属性一样的赋值, 而不是方法传参
  console.log(per.name);


})()

可以直接将属性定义在构造函数中

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

// 相当于
class A{
    name: string
    age: number
    constructor(name: string,age: number){}
}

泛型

(function (){
  // 定义函数或者类的时候, 如果类型不明确可以使用泛型
  // 和any的区别, any是关闭了检查, 泛型是一个占位模板
  function fn <T> (a:T) :T{
    return a
  }

  console.log(fn(123))
  console.log(fn(‘456‘))

  // 泛型可以设置多个
  function fn2 <T, K> (a:T, b: K) :T{
    console.log(b)
    return a
  }

  let b = fn2(789, ‘abc‘)
  console.log(b);

  // 泛型可以主动指定
  fn2<string, number>(‘qwe‘, 996)

  // 泛型继承接口, 就是说类型必须符合接口的格式
  interface Inter{
    length: number
  }

  function fn3<T extends Inter>(a:T) {
    return a.length  // 类型和接口一样, 有lenght属性
  }

})()

其他常见的webpack配置

  • less解析npm i -D less less-loader css-loader style-loader

  • css兼容加载器 npm i -D postcss postcss-loader postcss-preset-env

TypeScript基础

原文:https://www.cnblogs.com/jiutianzhiyu/p/14705861.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!