TypeScript基本类型、类、封装、继承、泛型、接口概念

TypeScript基本类型、类、封装、继承、泛型、接口概念,第1张

简介:前几篇介绍了Vue3的Composition API,Vue-Router,pinia。Vue3能更好支持TS,因此,本节将介绍TS,详细描述了TS的优缺点,安装,如何配置自动编译、tsconfig.json的常用配置,使用webpack打包时的webpack.config.js的配置,还会详细说明TS基本数据类型、对象、类、抽象类、构造方法、接口、继承、封装、泛型。

文章目录 一、初识TypeScript1、TS介绍2、TS 的优缺点 二、安装和环境搭建1、全局安装2、webstorm配置自动编译tsconfig.json常用配置 3、使用webpack打包编译ts代码1)新建空文件夹2)webpack.config.js3)package.json中添加4)打包 三、TypeScript 常用语法1、boolean/number/string2、null/undefined3、字面量4、any5、unknown6、void7、never8、object9、array10、tuple11、enum枚举12、其它用法 四、面向对象1、类、构造函数与抽象类:2、继承与super3、接口4、封装属性5、泛型:情况1:在函数中使用,可同时指定多个泛型情况2:在类中使用

一、初识TypeScript 1、TS介绍

​ TypeScript微软开发、跨平台的编程语言。它是JavaScript的超集,最终会被编译为JavaScript代码。

​ 2012年10月,微软发布了首个公开版本的TypeScript,2013年6月19日,在经历了一个预览版之后微软正式发布了正式版, TypeScript的作者是安德斯海尔斯伯格,C#的首席架构师。

​ TypeScript扩展了JavaScript的语法,所以任何现有的JavaScript程序可以运行在TypeScript环境中。

2、TS 的优缺点

优点:

​ TypeScript 是 JavaScript 的超集,.js 文件可以直接重命名为 .ts 即可

​ 即使没有显式的定义类型,也能够自动做出类型推论

​ 可以定义从简单到复杂的几乎一切类型

​ 即使 TypeScript 编译报错,也可以生成 JavaScript 文件

​ 兼容第三方库,即使第三方库不是用 TypeScript 写的,也可以编写单独的类型文件供 TypeScript 读取

​ 类型系统增加了代码的可读性和可维护性

​ 拥有活跃的社区,并且支持ES6规范

不足:

​ 需要理解接口(Interfaces)、泛型(Generics)、类(Classes)、枚举类型(Enums)等概念

​ 短期可能会增加一些开发成本,毕竟要多写一些类型的定义,不过对于一个需要长期维护的项目,TypeScript 能够减少其维护成本

​ 集成到构建流程需要一些工作量

​ 可能和一些库结合的不是很完美

二、安装和环境搭建 1、全局安装
npm install -g typescript   或者npm i -g typescript
tsc-V        //检查安装是否成功,Version 4.5.5
2、webstorm配置自动编译

添加tsconfig.json文件,执行命令tsc -w可编译并监视所有文件,tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译。

注:

​ include:指定哪些文件需要被编译,**表示任意目录,*表示任意文件

​ exclude:不需要被编译的文件目录,默认值[“node_modules”,“bower_comonents”,“jspm_packages”]

​ extend:定义被继承的配置文件,不常用

​ files:指定被编译文件的列表,只有被编译的文件比较少时才用

​ compilerOptions:lib:一般使用默认值; strict : 开启所有严格的类型检查,会同时配置:alwaysStrict、noImplicitAny、noImplicitThis、strictNullChecks

tsconfig.json常用配置
{
  "include": [ "./src/**/*"],
  "exclude": [ "./src/hello/**/*"],
  "compilerOptions": {
    "incremental": true, // TS编译器在第一次编译之后会生成一个存储编译信息的文件,第二次编译会在第一次的基础上进行增量编译,可以提高编译的速度
    "tsBuildInfoFile": "./buildFile", // 增量编译文件的存储位置
    "diagnostics": true, // 打印诊断信息
    "target": "es2017", // 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'esnext'
    "module": "amd", //  'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'es2020', 'es2022', 'esnext', 'node12', 'nodenext'
    "outFile": "./dist/app.js", // 所有全局作用域中的代码都会合并到一个文件中,注意:要合并的话,module必须是amd和system
     "lib": ["DOM", "ES2015", "ScriptHost", "ES2019.Array"], // TS需要引用的库,即声明文件,es5 默认引用dom、es5、scripthost,如需要使用es的高级版本特性,通常都需要配置,如es8的数组新特性需要引入"ES2019.Array",
    "allowJs": true, // 是否允许编译JS文件,默认是false
    "checkJs": true, // 允许在JS文件中报错,通常与allowJS一起使用
    "outDir": "./dist", // 指定编译后的文件存放的目录,源码与编译后区分开了
    "declarationMap": true, // 为声明文件生成sourceMap
    "removeComments":false, //编译后是否删除注释
    "noEmit": false, // 编译后不会生成任何js文件,当只想使用语法检测功能时用设置为true
    "noEmitOnError": true, // 发送错误时不输出任何文件
    "strict": true, // 开启所有严格的类型检查,如:alwaysStrict、noImplicitAny、noImplicitThis、strictNullChecks
    ...
  }
}
3、使用webpack打包编译ts代码 1)新建空文件夹
npm init -Y  //在空文件夹下生成package.json
npm install -D webpack webpack-cli typescript ts-loader   //安装依赖
npm install -D html-webpack-plugin   //webpack的插件,作用是自动生成index.html文件
npm install-D webpack-dev-server     //webpack的启动服务
npm install -D clean-webpack-plugin   //webpack插件,作用清除dist内容,保证每次Build都是最新文件
npm install -D @babel/core @babel/preset-env babel-loader core-js    //安装bable,兼容不同浏览器 
2)webpack.config.js
const path = require('path')    //引入一个包
const HTMLWebpackPlugin = require('html-webpack-plugin')   //引入HTML插件
const {CleanWebpackPlugin} = require('clean-webpack-plugin')  //引入clear-webpack-plugin 插件
module.exports = {  //webpack的所有配置信息都写在module.exports
   mode:'development',// development为开发者环境,production为生产环境变量 ,还有一个为none
 	entry:"./src/index.ts" , //指定入口文件
   output: {    //指定打包文件所在目录
    path:path.resolve(__dirname,'dist'),   //指定打包文件的路径
    filename: "bundle.js"  //打包后文件的名称
  },
  module: {       //指定webpack打包时使用的模块
    rules: [{
      test:/\.ts/,   //test指定的是规则生成的文件
      use:[    //要使用的loader
            {
              loader: "babel-loader",   //配置bable,指定加载器
              options: {
                presets:[   //设置预定义的环境
                  "@babel/preset-env",  //指定环境的插件
                  {   //配置信息
                    targets:{   //要兼容的目标浏览器
                      "chrome":"88"
                    },
                    "corejs":"3",  //指定corejs的版本
                     "useBuiltIns":"usage",//使用corejs的方式"usage" 表示按需加载
                  }
                ]
              }
            },
          'ts-loader'
      ],
      exclude: /node_modules/,  //要排除被编译的文件
    }]
  },
  plugins: [    //配置webpack插件
     new CleanWebpackPlugin(),
     new HTMLWebpackPlugin({      //自动生成html文件
       template: "./src/index.html"    //提供的模板
    }),
  ],
  resolve: {    //用来设置引用模块
    extensions: ['.ts','.js']   //可以引用ts、js文件
  }
}
3)package.json中添加
"build": "webpack"
4)打包
npm run build   //在dist下得到打包文件bundle.js及index.html
三、TypeScript 常用语法

javascript有七种原始数据类型,boolean、number、string、null、undefined 、Symbol (ES6)和 BigInt (ES10)

​ typescript的基本类型有:boolean、number、string、null、undefined 、字面量(限定变量的值就是该字面量的值)、any、unknown(类型安全的any)、void(空值)、never(没有值)、object、array、tuple(元组)、enum(枚举)

1、boolean/number/string
let a:boolean = true
let b:string = 'wl'
let c:number = 12
2、null/undefined
const onlyNull: null = null;
const onlyUndefined: undefined = undefined;
3、字面量
let a:25    //a永远是25
//使用联合类型
let b :"male"| "female"
let c:string|number|boolean    //使用广泛
4、any

任意类型,一个变量设置为any,相当于对该变量关闭了TS的类型检测;使用ts时不建议使用any;

注:声明变量不指定类型,TS解析器自动判断变量是any类型(隐式any)

let d:any  //显式any
let a      //隐式any,自动判定a类型为any
5、unknown

表示未加类型的值

注:any与unknown区别:unknown是一个类型安全的any,unknown类型的变量不能直接赋值给其它变量;使用unknown类型给其它赋值,需要先判断类型

let e:unknown
let s:string
if(typeof e === "string"){    //使用unknown类型给其它赋值,需要先判断类型
    s = e
}
//类型断言,告诉解析器实际类型
s = e as string   //变量 as 类型
s = <string>e     //<类型>变量
6、void

表示为空,以函数为例,表示没有返回值

function fn():void {
    return
}
7、never

表示没有值,不会有返回结果,使用率较少

function fn2():never {
    throw new Error('出错了')
}
8、object

表示一个js对象

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

定义函数,设置函数结构的类型声明,语法:(形参:类型,形参:类型,…)=>返回值类型

let a:object   //不常用
a = {}/[]/function () {}
let b:{name:string,age:number,height?:number}  //?表示此属性是可选的
b = {name:'wl',age:123}
let c:{name:string,[propName:string]:any}    //定义对象,[propName:string]:any 表示任意类型的属性
c={name:'dsk',a:12,b:'fd'}
let d:(a:number,b:number)=>number         //定义函数,设置函数结构的类型声明 语法:(形参:类型,形参:类型,...)=>返回值类型
d = function (a:12,b:23):number {
    return a+b
}
9、array

两种写法:类型[ ] (如:string[ ],number[ ]) ;Array<类型>(如:Array,Array)

let e:string[]= ['1','2']
let f:number[]=[1,2]
let g: Array<string> = ['a','b']
10、tuple

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

let h :[string,string] =  ['1','2']
11、enum枚举
enum Gender{
    Male,
    Female = 1
}
let i:{gender:Gender}
i = {
    gender:Gender.Female
}
12、其它用法
//使用&表示同时
let hh :{name:string} & {age:number}
hh={name:'wl',age:2}
//类型别名
type  myType = 1|2|3|4
let k :myType
四、面向对象

要想面向对象, *** 作对象,首先便要拥有对象,那么下一个问题就是如何创建对象,要创建对象,必须要先定义类,所讲的类可以理解为对象的模型,程序中可以根据创建指定类型的对象,举例来说:可以通过Person类来制建人的对象,不同的类可以用来创建不同的对象。

1、类、构造函数与抽象类:

使用class定义,对象中包含属性和方法

注:直接定义的属性是实例属性/方法,通过对象的实例去访问;

readonly开头的属性表示一个只读属性,不能被修改;

属性/方法以static开头,定义的是静态属性/方法,直接通过类访问,无需创建对象;

在实例方法中,this就表示当前实例;

​ 以abstract开头的是抽象类,抽象类可以被继承,但不能创建对象;

抽象类可以有抽象方法,使用abstract开头定义抽象方法,抽象方法只能定义在抽象类中并且没有方法体,子类必须对方法进行重写

class Person{
    static readonly name:string//定义的实例属性,readonly表示只读不能被修改,static定义静态属性
    age:number
    constructor(name:string,age:number){ //构造函数
        this.name=name;this.age = age
    }
    static sayHello(){}   //定义方法,类的静态方法
}
const per = new Person('ww',1)  //通过实例对象访问属性,如per.name
Person.sayHello  //前有static,直接就能访问到类属性

(function(){
    abstract class Animal{      //定义抽象类
    name:string;
    constructor(name:string){this.name = name}
    abstract sayMethod():void;   //使用abstract开头定义抽象方法,抽象方法只能定义在抽象类中并且没有方法体,子类必须对方法进行重写
}
class dog extends Animal{
    sayHello(){console.log('重写父类方法')}
}
})()
2、继承与super

注:

extends继承父类的方法

定义一个类,在子类中添加与父类相同的方法,将覆盖父类的方法;子类覆盖父类叫方法的重写

super继承父类的属性与方法

(function(){
   class Animal{
        name:string;
        constructoe(name:string){this.name = name} 
        sayHello(console.log('叫')) 
   }
   class dog extends Animal{
       gender:string
       constructor(name:string,gender:string){
           super(name)  //调用父类构造方法
           this.gender = gender      
       }
       sayHello{   //继承方法
           super.sayHello()       
       }
       run(){}   //新增加方法
   } 
})()
3、接口

定义类时,可以用类去实现接口,实现类就是使类满足接口,接口就是对类的限制

接口用来定义类的结构,定义一个类中包含哪些属性方法,接口也可以当做类型声明,接口可以重复申请

接口在定义类的时候限制类的结构,接口只定义对象的结构,不考虑实际值,在接口中所有的方法都是抽象方法

(function(){
    interface myInter{    
        name:string;
        sayhello():void;    
    }
    class myclass implements myInter{   //用类实现接口,接口就是对类的限制
        name:string;
        constructor(name:string){this.name = name}  
        sayhello(){}          
    }
})()
4、封装属性

ts在类的属性前添加修饰符:

public:可在任意位置访问,是默认值;

private:私有属性,私有属性只能在类内部访问(修改),在类内添加方法,私有属性可被访问;

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

注:

由于属性是在对象中设置的,属性可以任意的被修改,将会导致对象中的数据变得非常不安全。因此需要对属性进行封装。

js封装的属性存取器使用时需要调用相应的getter和setter方法;而ts封装的属性存取器使用时可直接当作变量来用就行。

加getter和setter方法只是为了对属性的值做判断,如果不需做判断则没必要使用。

(function(){
  class A {     //定义类时可以直接将属性定义在构造函数中(简化代码)
     constructor(public name:string,private age:number){            
    }
    get age(){ return this.name;}
    set age(value:string){
        if(value>=0){  this.name = value;}  
    }
}
const a = new A('ww',11)
a.name   //可直接访问
a.age = -13  //不符合判断条件,不被执行
})()
5、泛型:

作用:当定义的函数、类没有明确的类型时使用泛型

情况1:在函数中使用,可同时指定多个泛型
function fn1<T,K>(a:T,b:K){
    console.log(b)
    return a
}
//泛型实现接口继承
Interface inter{
    length:number
}
function fun2<T extends inter>(a:T){   //T extends inter表示泛型T必须是Interface的实现类(子类)
    return a.length
}
情况2:在类中使用
class myclass<T>{
    name:T;
    constructor(name:T){this.name = name}
}
const mc = new myclass<string>('qq')

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/930044.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-17
下一篇 2022-05-17

发表评论

登录后才能评论

评论列表(0条)

保存