TypeScript 学习

一、内容概要

  1. 强类型与弱类型
  2. 静态类型与动态类型
  3. JavaScript 自有类型系统的问题
  4. Flow 静态类型检查方案
  5. TypeScript 语言规范与基本应用

二、强类型和弱类型(类型安全)

  1. 强类型(TypeScript):
    1. 语言层面限制函数的实参类型必须与形参类型相同。
    2. 更强的类型约束。
    3. 强类型中不允许有任意的隐式类型装换。
  2. 弱类型(JavaScript):
    1. 弱类型语言层面不会限制实参的类型。

三、动态类型和静态类型(类型检查)

  1. 静态类型(TypeScript):
    1. 一个变量在声明时,它的类型就是确定的。
    2. 声明过后,它的类型就不允许再被修改。
  2. 动态类型(JavaScript):
    1. 运行阶段才能确定变量的类型。
    2. 变量的类型能够随时发生变化。

四、JavaScript 类型系统特征

  1. JavaScript 是一门弱类型和动态类型的语言。
  2. JavaScript 是一门脚本语言,没有编译环节。

五、弱类型的问题

  1. 弱类型只有在编译时才能发现问题。
  2. 类型没有确定,容易发生一些错误。
  3. 对对象错误的用法。

六、强类型的优势

  1. 错误可以更早的暴露。
  2. 代码更加智能,编码更准确。
  3. 重构更牢靠。
  4. 减少不必要的类型判断。

七、Flow

1.概述

  • Flow 是 JavaScript 的一款静态类型检查器

  • 类型注解

    function sum (a:number, b: number) {
    	return a + b;
    }
    

2.Flow 快速上手

  1. 安装 Flow (类型检查)

    // 命令行中先初始化,以包的形式去安装
    yarn init --yes			// 初始化
    yarn add flow-bin  		// 安装flow
    // vscode 移除编辑器自带的错误检查 ctrl + , 打开弹框,查找处输入 javascript validate 多选框的钩给去掉。
    flow init				// 初始化flow
    yarn flow				// 执行flow 进行类型验证
    
  2. 在 .js 文件中需要 flow 进行类型检查,需要在头部添加 // @flow 标记

3.Flow 编译移除注解

  1. 通过 flow-remove-types 移除注解

    // 安装 flow-remove-types 插件
    yarn add flow-remove-types --dev			
    
    // 移除注解
    yarn flow-remove-types . -d dist			// . 是当前目录  dist执行后的文件
    
  2. 通过 babel 移除注解

    // 安装 babel 包
    yarn add @babel/core @babel/cli @babel/preset-flow --dev
    
    // 添加 babel 配置文件 .babelrc 文件
    // 文件中配置
    {"presets":["@babel/presets-flow"]}
    
    yarn bable src -d dist
    
  3. Flow 在vscode 中开发工具插件 Flow Language Support 安装,每次保存过后自动检查类型错误。

八、TypeScirpt

1.TypeSript介绍:

  1. TypeScript 是微软开发的一款开源的编程语言。
  2. TypeScript 是 JavaScript 的超集,遵循了最新的 es5、es6 规范。TypeScript 扩展了 JavaScript 的语法。
  3. TypeScript 更像后端 Java、C# 这样的面向对象语言,可以让 JS 开发大型企业项目。
  4. 谷歌也在大力支持 TypeScript 的推广,谷歌的 Angular2.x+ 就是基于 TypeScript 语法。
  5. 最新的 Vue 、React 也可以集成 TypeScript。
  6. Nodejs 框架 Nestjs、midaway 中用的就是 TypeScript 语法。

2.TypeScript 安装、编译

  1. 安装

    // npm 安装
    npm install -g typescript
    // cnpm 安装
    cnpm install -g typescript
    // yarn 安装
    yarn global add typescript
    
  2. 编译

    // 命令行:
    tsc helloWorld.ts
    // 安装 ts-node插件
    ts-node helloWorld.ts
    

3.Vscode 自动编译 .ts 文件

  1. 创建 tsconfig.json 文件 tsc --init 生成配置文件

    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5NbaGvOv-1619423482612)(D:\personal\大前端高薪训练营-拉钩\笔记\image-20210412094932887.png)]
  2. 老版本 vscode 点击: 任务->运行任务-> tsc:监视-tsconfig.json 然后就可以自动生 成代码了

  3. 最新版本 vscode 点击: 终端->运行任务->typescript->tsc:监视-tsconfig.json 然后就 可以自动生成代码了

九、TypeScript 中的数据类型

1.TypeScript 数据类型

  • TypeScript 中为了使编写的代码更规范,更有利于维护,增加了类型校验。
  1. 布尔类型(boolean)
  2. 数字类型(number)
  3. 字符串类型(string)
  4. 数组类型(array)
  5. 元组类型(tuple)
  6. 枚举类型(enum)
  7. 任意类型(any)
  8. null 和 undefined
  9. void 类型
  10. never 类型

2.定义类型示例

  1. 布尔类型

    let bool: boolean = true;
    
  2. 数字类型

    let num: number = 11;
    
  3. 字符串类型

    let str: string = 'lin';
    
  4. 数组类型

    // 第一种定义方式
    let arr: string[] = ['lin','xing'];
    // 第二种定义方式: 泛型
    let arr: Array<string> = ['lin','xing'];
    // 第三种类型:
    let arr: any[] = ['linxing', 123, false];
    
  5. 元组类型

    let tup: [string, number, boolean] = ['JavaScript', 110, true];
    
  6. 枚举类型

    enum 枚举名{
    	标识符[= 整型常数],
    	标识符[= 整型常数]....
    	标识符[= 整型常数]}
    enum Flag{ success = 1, error = 2};
    let f:Flag = Flag.success;
    console.log(f);   // 结果1
    
  7. 任意类型

    let anyType: any = 'string'			// 什么类型都能放
    
  8. null 和 undefined 类型

    let age: number | undefined;			// | 或者的意思
    let num: number | null | undefined;
    
  9. void 类型

    // void 表示没有任何类型,一般用于执行方法没有返回值
    function sum(x, y,): void{
        let num: number = x+y;
    }
    
  10. never 类型

    // never类型:是其他类型(包括 null 和 undefined )的子类型,代表从不会出现的值。
    // 这意味着声明never的变量只能被never类型所赋值。
    

十、TypeScript 函数

1.TypeScript函数

  1. es5中定义方法

    // 函数声明式
    function sun() {};
    // 匿名函数
    let person = function(){};
    
  2. TypeScript中定义方法

    // 函数声明式
    function sun():viod{};
    // 匿名函数
    let person = funciton():string{ return  ''}
    

2.函数方法传参

  1. 函数声明

    function getInfo(name: string, age: number): string{ 
    	return `我的名字叫${name},今年${age}岁`
    }
    
  2. 匿名函数

    let getInfo = function(name: string, age: number): viod{ 
    	console.log(`我的名字叫${name},今年${age}岁`)
    }
    

3.方法的可选参数

  1. es5 里面方法的实参和形参可以不一样,但是 ts 中必须一样,如果不一样就需要配置可选参数

  2. 注意!可选参数必须配到参数的最后面

    let getInfo = function(name: string, age?: number): viod{ 
    	if(age){
    		console.log(`我的名字叫${name},今年${age}岁`)
    	}else{
    		console.log('哈哈哈')
    	}
    }
    

4.方法的默认参数

  1. es5 中是不能配置默认传参的,es6 和 ts 可配置默认参数

    let getInfo = function(name: string, age: number = 23): viod{ 
    	if(age){
    		console.log(`我的名字叫${name},今年${age}岁`)
    	}else{
    		console.log('哈哈哈')
    	}
    }
    

5.函数剩余参数

  1. 三点运算符 接收传递过来的所有参数

    function sum(a:number, ...result: number[]): number{
    	var sum = 0;
    	for(let i = 0; i<result.lenght;i++){
    		sum+=result[i];
    	}
    	return sum
    }
    

6.函数重载

  1. java 中方法的重载:重载指的是两个或者两个以上同名函数,但它们的参数不一样,这时会出现函数重载的情况。

  2. typescript 中的重载:通过为同一个函数提供多个函数类型定义来试下各种功能的目的。

  3. 为了兼容es5,以及es6中重载的写法和java有区别

    function getInfo(names: string): string;
    function getInfo(age:number ): string;
    function getInfo(str:any):any {
    	if(typeof str === 'string'){
    		return `我叫:${str}`
    	}else{
    		return `我的年龄是${str}`
    	}
    }
    

十一、TypeScript 中的类

class Person{
	name:string;
	constructor(name: string){			// 构造函数  实例化类的时候触发的方法
		this.name = name;
	}
    getName(): string{
        return this.name
    }
    setName(name:string):viod {
        this.name = name;
    }
}

1.TypeScript 中类继承

// extends、super
class Person{
	name:string;
	constructor(name: string){			// 构造函数  实例化类的时候触发的方法
		this.name = name;
	}
    getName(): string{
        return this.name
    }
    setName(name:string):viod {
        this.name = name;
    }
}
定义 web 类来继承 Person 类
class Web extends Person{
	constructor(name:string){
		super(name)						// 初始化父类的构造函数				
	}
}
let w = new Web('李四')

2.TypeScript类里面的修饰符

  1. TypeScript 里面定义了属性的时候给我们提供了三种修饰符
    1. public:公有 在类里面、子类、类外都可以访问
    2. protected:保护类型 在类里面、子类里面可以访问,在类外部没法访问
    3. private:私有 在类里面可以访问,子类、类外部都没法访问
  2. 属性不加修饰符:默认代表共有属性,public
class Person{
	public name:string;
	constructor(name: string){			// 构造函数  实例化类的时候触发的方法
		this.name = name;
	}
    getName(): string{
        return this.name
    }
    setName(name:string):viod {
        this.name = name;
    }
}

十二、TypeScript 中类的静态属性、静态方法、抽象类、多态

1.es5中的静态属性、静态方法

function Person(){}
Person.name = 'linxing';		// 静态属性
Person.sayName = function(){ console.log(this.name) }  // 静态方法


Jquery
$(.box).css();
function $(el){    return Base(el)}
Base(){   this.css = '获取DOM节点'}

2.TypeScript中静态属性、静态方法

class Person{
	public name: string
	static age: number
	constructor(name:string){
		this.name = name
	}
	sayName(){		// 实例方法
		
	}
	static print(){		// 在静态方法里面不能使用this
		console.log('我这是静态方法')
	}
}

3.多态方法

  1. 父类定义一个方法不去实现,让继承它的子类去实现 每一个子类有不同的表现
  2. 多态属于继承
class Animal{
	name: string
	constructor(name:string){
		this.name = name
	}
	eat(){							// 定义了一个方法不去实现,让子类去实现
		console.log('我是吃的方法')
	}
}
class Dog extends Animal{
	constructor(name:string){
		super(name)
	}
	eat(){							// 这就是多态, 继承重写了父类方法
		console.log('小狗吃粮食')
	}
}
class Cat extends Animal {
	constructor(name:string){
		super(name)
	}
	eat(){
		console.log('吃老鼠')
	}
}

4.抽象方法

  1. typeScript 中的抽象类:它是提供其他类继承的基类,不能直接被实例化。
  2. 用 abstract 关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。
  3. abstract 方法只能放在抽象类里面
  4. 抽象类和抽象方法用来定义标准,标准:Animal 这个类要求它的子类必须包含 eat 方法
abstract class Animal{				// 父类定义,子类必须实现
    public names: string
    constructor(name:string) {
        this.names = name;
    }
	abstract eat():any;
}
// let p = new Animal()  错误:无法定义抽象类

class Dog extends Animal{
  constructor(name:string){
    super(name)
  }
  eat(){
    console.log(this.names + '吃');
  }
}

十三、TypeScrip 中的接口

1.接口的概念

  1. 接口的作用:在面向对象的编程中,接口时一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。typescript 中的接口类似于 java ,同时还增加了更灵活的接口类型,包括属性、函数、可索引、和类等。
  2. 定义行为和动作的规范。对批量方法进行约束 interface

2.属性类接口

  1. 就是传入对象的约束 属性接口

    interface FullName{
    	firstName: string;		// 注意,分号结束
    	secondName: string;
    }
    function printName(name:FullName){
    	// 必须传入firstName  secondName
        console.log(name.firstName + name.secondName)
    }
    
  2. 可选接口

    interface FullName(){
    	firstName: string;
    	secondName?:string
    }
    function getName(name:FullName){
    	console.log(name)
    }
    // 参数的顺序可以不一样
    getName({
    	firstName:'linxing';
    	secondName:'liner'
    })
    
  3. 示例

    interface Config{
    	type: string;
    	url: string;
    	data?: string;
    	dataType: string
    }
    function ajax( config: Config ){
        var xhr = new XMLHttpRequest();
        xhr.open( config.get, config.url, true);
        xhr.send(config.data);
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4 && xhr.status == 200){
                if(confiig.dataType == 'json'){
                    JSON.perse(xhr.responseText)
                }else{
                    console.log(xhr.reponseText)
                }
            }
        }
    }
    ajax({
        type:'get',
        data:'name:zhang',
        url: 'http://www.baidu.com',
        dataType:'json'
    })
    

3.函数类接口

  1. 函数类型接口:对方法传入的参数 以及返回值进行约束 批量约束

  2. 加密的函数类型接口

    interface encrypt{
    	(key:string,value:string):string;
    }
    var md5:encrypt = function (key:string,value:string): string{
    	// 模拟操作
    	return key + name
    }
    

4.可索引接口

  1. 可索引接口:对数组、对象的约束(不常用)

  2. 数组的约束

    interface UserArr{
    	[index:number]:string
    }
    let arr:UserArr = ['lixing']
    
  3. 对象的约束

    interface UserArr{
    	[index:string]:any
    }
    let arr:UserArr = {
    	name: '张三',
    	age: 23	
    }
    

5.类类型接口

  1. 类类型接口:对类的约束 和 抽象类比较相似

    interface Animal{
      name:string;
      eat(str:string):void
    }
    
    class Dog implements Animal{
      name:string;
      constructor(name:string){
        this.name = name
      }
      eat(){
        console.log('小黑吃粮食!');
      }
    }
    let p = new Dog('小黑');
    p.eat();
    

6.接口扩展 接口可继承接口

interface Animal{
  eat(foot:string):string;
}
interface Web extends Animal{
  work():void;
}

class Person implements Web{
  public name:string;
  constructor(name:string){
    this.name = name
  }
  eat(foot:string){
    return `${this.name}${foot}`
  }
  work(){
    console.log(`${this.name}敲代码`);
  }
}
let p = new Person('小林');
console.log(p.eat('粮食'));
p.work()

十四、TypeScript 中的泛型

1.泛型的概念:

  1. 软件工程中,我们不仅要创建一致的定义良好的 API,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
  2. 在像 C# 和 Java 这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类的数据。这样用户就可以以自己的数据类型来使用组件。
  3. 通俗理解:泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持。

2.泛型函数

// 泛型:可以支持不特定的数据类型  要求:传入的参数和返回的的参数一致
// T表示泛型,具体什么类型是调用这个方法的时候决定的
	function getData<T>(value:T):T{
		return value;
	}
	getData<number>(123)

	function getData<T>(value:T):any{
		return value;
	}
	getData<number>(123)

3.泛型类

  1. 泛型类:比如有个最小堆算法,需要同时支持返回数字和字符串你两种类型。通过类的泛型来实现

    class MinClass<T> {
      public list: T[] = [];
      add(num: T): T[]{
        this.list.push(num)
        return this.list
      }
      minNum():T{
        let min = this.list[0];
        for (let i = 0; i < this.list.length; i++) {
          const element = this.list[i];
          if (min > element) {
            min = element
          }
        }
        return min
      }
    }
    let person = new MinClass<string>();		// 实例化类,并且证明类的泛型是number 
    console.log(person.add('a'));
    console.log(person.add('c'));
    console.log(person.add('e'));
    console.log(person.minNum());			
    

4.泛型接口

  1. // 泛型接口
    interface ConfigFn{
    	<T>(value:T):T;
    }
    let getData:ConfigFn = function<T>(value:T):T{
    	return value;
    }
    getData<string>('张三')
    
  2. // 泛型接口
    interface ConfigFn<T>{
    	(value:T):T;
    }
    function getData<T>(value:T):T{
    	return value;
    }
    let myGetData:ConfigFn<string> = getData;
    myGetData('张三');
    

十五、TypeScript 泛型类 把类作为参数类型的泛型类

// 操作数据库的泛型类
calss MysqlDb<T>{
	add(info:T):boolean{
		console.log(info);
		return true
	}
}

//1、定义一个User类和数据库进行映射

class User{
    username:string | undefined;
    pasword:string | undefined;
}
var u = new User();
u.username = '张三';
u.password = '123456';
var Db = new MysqlDb<User>();
Db.add(u)

1.统一封装 Mysql、Mssql、mongodb

  1. 功能:定义一个操作数据库的库 支持 Mysql Mssql MongoDb
  2. 要求:Mysql Mssql MongoDb 功能一样 都有 add update delete get方法
  3. 注意:约束统一的规范、以及代码重用
  4. 解决方案:需要约束规范所以要定义接口,需要代码重用所以用到泛型
    1. 接口:在面向对象的编程中,接口时一种规范的定义,它定义了行为和动作的归覅能否
    2. 泛型 通俗理解:泛型就是解决 类 接口 方法的复用性。
interface DBI<T>{
    add(info:T):boolean;
    update(info:T,di:number):boolean;
    delete(id:number):boolean;
    get(id:number):any[];
}
// 定义一个操作mysql数据库的类     注意:要实现泛型接口 这个类也应该是一个泛型类
class MysqlDb<T> implements DBI<T>{
  add(info: T): boolean {
    console.log(info)
    return true
  }
  update(info: T, di: number): boolean {
    throw new Error("Method not implemented.");
  }
  delete(id: number): boolean {
    throw new Error("Method not implemented.");
  }
  get(id: number): any[] {
    throw new Error("Method not implemented.");
  }
}
class User{
    userName: string | undefined;
    password: string | undefined;
}
let person = new User();
person.userName = 'linxing';
person.password = '123456'

let OMysqlDb = new MysqlDb<User>()
OMysqlDb.add(person);

十六、TypeScript中的装饰器

1.什么叫装饰器?

  1. 装饰器:装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或传参上,可以修改类的行为。
  2. 通俗的讲 装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。
  3. 常见的装饰器有:类装饰器、属性装饰器、方法装饰器、参数装饰器
  4. 装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可传参)
  5. 装饰器是过去几年中 JS 最大的成就之一,已是 es7 的标准特性之一

2.装饰器的类别

  1. 类装饰器:类装饰器在类声明之前被声明(紧靠着类声明)。类装饰器应用于类构造函数,可以用来监视,修改或替换类定义。传入一个参数

  2. 普通装饰器(没有参数)

    function logclass(parms:any){
      parms.prototype.sayName = function () {
        console.log(this.name);
      }
    }
    @logclass
    class Web {
      public name:string;
      constructor(name:string){
        this.name = name
      }
    }
    let person:any  = new Web('linxing');
    console.log(person);
    person.sayName();
    
  3. 装饰器工厂(带参)

    // 装饰器
    function logclass(params:string){
      return function(target:any){
    q    target.prototype.apiUrl = params;
      }
    }
    @logclass('http://www.itying.com/api')
    class Web {
      constructor(){}
    }
    let person:any  = new Web();
    console.log(person.apiUrl);
    
  4. 类装饰器重载 类的构造函数

    // 装饰器
    function logclass(target:any){
      console.log(target);
      return class extends target{
        apiUlr:any = '我是修改过后的数据';
        getData(){
          console.log(this.apiUlr);
        }
      }
    }
    @logclass
    class Web {
      public apiUlr: string | undefined;
      constructor(){
        this.apiUlr = '我是构造函数里的apiurl'
      }
      getData(){}
    }
    let person:any  = new Web();
    console.log(person.apiUlr);
    
  5. 属性装饰器

    1. 属性装饰器表达式会在运动时当作函数被调用,传入下列2个参数
    2. 对于静态成员来说是类的构造函数,对于实例成员是类的对象
    3. 成员的名字
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值