TypeScript学习笔记

TS 安装

npm i -g typescript

tsc index.ts 会将ts文件编译成对应的js文件

创建tsconfig.json文件


tsc --init

"outDir": "./js"

终端 配置任务  监视tsconfig
终端 运行任务  监视tsconfig

基本数据类型

  • 布尔类型 boolen
  • 数字类型 number
  • 字符串类型 string
  • 数组类型 array
  • 元组类型 tuple
  • 枚举类型 enum
  • 任意类型 any
  • null和 undefined
  • void类型
  • never类型


var arr: number[] = [1,2,12]

var arr:Array = [1,2,111]


> 给数组中每一个位置指定对应的类型

let arr:[number, string] = [123,'ssss']


> 标识符不赋值的话 值为其下表
enum Flag {
  success = 1,
  error,
  'normal'
}

let s:Flag = Flag.success
let e: Flag = Flag.error
let n: Flag = Flag.normal
s => 1
e => 1
n => 2


var box:any = document.getElementById('box');
box.style.color='red'


> 其他类型(never类型)的子类型

var num:number | null | number;


> 是其他类型 包括null 和undefined 的子类型 代表从不会出现的值
> 一位置never类型的变量只能被never类型所赋值

函数

function run (name:string , num?:number=20, ...result:number[] ): void {

}

? 表示可选参数,要放到必传参数的后面 


> 为同一个函数提供多个函数类型定义来实现多种功能的目的

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

ES5中的继承通过原型链继承和对象冒充继承来实现
两个同时用才能实现需求

function Son (name, age) {
  Person.call(this, name, age) // 对象冒充继承 可以继承构造函数里面的属性和方法, 但是不能继承原型链上的属性和方法
}

Son.prototype = Person.prototype // 原型链继承可以继承父类方法但是不能传参

ES5中的静态属性和方法
> 可以直接通过类名调用
Son.name = 'jack'
Son.run = function() {}

ES5中的实例属性和方法
写在类中,通过new出的实例调用的

TS中的类

class Person {
  name: string; // 属性 前面省略了public关键字
  constructor (n: string) {
    this.name = n
  }
  getName (): string {
    return this.name
  }
  setName (name: string): void {
    this.name = name
  }
}

let p = new Person('a')
console.log(p.getName) => a
p.setName('b') 
console.log(p.getName) => b

TS中的继承

class student extends Person {
  constructor(name:string) {
    super(name) // 初始化父类的构造函数
  }
}

类中修饰符

  • public
  • private 只能在当前类使用
  • protected 受保护的:只能在当前类和子类中访问, 不能通过实例访问

静态方法

class Person {
  name: string; // 属性 前面省略了public关键字
  static: age: number = 20; // 静态属性 可以通过类名直接访问
  constructor (n: string) {
    this.name = n
  }
  getName (): string {
    return this.name
  }
  setName (name: string): void {
    this.name = name
  }

  static run():viod { // static修饰的静态方法 直接通过类名调用,不能直接调用类里面的属性,但是可以调用静态属性
  }
}

多态

父类定义一个方法 在子类中实现,每个子类有不同的表现

抽象方法抽象类

抽象类: 提供其他类继承的基类, 不能直接被实例化
使用abstract关键字定义抽象类和抽象方法
抽象类中的抽象方法不包含具体实现, 必须在派生类中实现
abstract抽象方法只能放在抽象类中

abstract class Animal {
  name:string;
  constructor (name:string) {
    this.name = name
  }
  abstract eat():any; 
}

class Dog extends Animal {
  constructor (name:string) {
    super(name)
  }
  // 抽象类的子类必须实现抽象类里面的抽象方法
  eat () {
    console.log(this.name+'eat')
  }
}

接口

用于规范的定义

  1. 对象的约束 属性接口
interface FullName {
  firstName: string;
  secName: string;
}

function printName (name: FullName) {
  // 必须传入name并且格式必须满足FullName
  console.log(name.firstName, name.secName)
}
let obj = { // 传入的参数必须包含 批量验证会报错 建议严格按照接口要求
  age: 20,
  firstName: 'jack';
  secName: 'ma';
}
printName(obj) 

printName({ 
  age: 20, // 此时会报错
  firstName: 'jack';
  secName: 'ma';
}) 


interface FullName {
  firstName: string;
  secName?: string; // 加? 可传可不传
}

  1. 函数类型接口:对方法传入的参数 以及返回值进行约束
interface encrypt {
  (key:string, value:string): string;
}
let md5:encrypt = function(key:string, value:string): string {
  return key+value
}
  1. 可索引接口: 数组,对象的约束 (不常用)

interface UserArr {
  [index:number]: string;
}
let arr: UserArr = ['aaa','bbb'];
console.log(arr[0])

interface UserObject{
  [index:string]:string
}
var obj:UserObject = {name: 'kaka'}
  1. 类 类型接口 对类的约束
interface Animal {
  name:string;
  eat (str:tring):void;
}

class Dog implements Animal {
  name:string;
  constructor(name:string) {
    this.name = name;
  }
  eat () {
    console.log(this.name)
  }
}

let d = new Dog('wangwang')
  1. 接口的扩展
interface Animal {
  eat():void;
}

inetrface Person extends Animal {
  work():void;
}

Class Studet implements Person {
  name: string;
  constructor (name:string) {
    this.name = name;
  }
  eat () {
    
  }
  work () {

  }
}

泛型

可以支持不特定的数据类型
具体什么类型是调用这个方法的时候决定的

function getData(value:T):T {
  return value;
}

getData (123);

getData ('ja');

类的泛型

class MinClass {
  public list:T[] = [];
  add(value:T):void {
    this.list.push(value);
  }
  min():T {
    var minNum = this.list[0];
    this.list.forEach(e => {
      if(minNum>e) {
        minNum = e
      }
    })
    return minNum
  }
}

let m1 = new MinClass(); // 实例化类 并且指定了T代表的类型是number
let m2 = new MinClass();

泛型接口


interface ConfigFn {
  (value:T):T;
}

let getData:ConfigFn = function(value:T):T{
  return value;
}

getData('jack')
getData(11122)

interface ConfigFn {
  (value:T):T;
}

function getData(value:T):T {
  return value
}

var myGetData:configFn=getData;

myGetData('www')

泛型类

将类作为泛型 用于约束

class User {
  name: string| undefined;
  pwd: string| undefined;
}

class MysqlDb {
  add(user:T): Boolean {
    return true
  }
}

ley u = new User();
u.name='a';
u.pwd='pwd';

let Db = new MysqlDb();
Db.add(u);

综合案例

定义一个操作数据库的库, 支持mysql mssql mongodb
要求

  • 都有增删改查
  • 约束同意规范 代码重用
// 1. 首先制定一个接口

interface DBI {
  add(info:T):boolean;
  update(info:T, id:number):boolean;
  delete(id:number):boolean;
  get(id:number):any[];
}

// 2. 定义一个操作mysql数据库的类 注意:要实现泛型接口 这个类也应该是一个泛型类

class MysqlDb implements DBI {
  add(info: T): boolean {
    console.log(info)
    return true;
  }  update(info: T, id: number): boolean {
    console.log(info,id)
    return true;
  }
  delete(id: number): boolean {
    console.log(id)
    return true;
  }
  get(id: number): any[] {
    console.log(id)
    return [];
  }
}

// 3.mssql 的

class Mssql implements DBI {
  add(info: T): boolean {
    console.log(info)
    return true;
  }  update(info: T, id: number): boolean {
    console.log(info,id)
    return true;
  }
  delete(id: number): boolean {
    console.log(id)
    return true;
  }
  get(id: number): any[] {
    console.log(id)
    return [];
  }
}

// 4.  操作

class User {
  name: string | undefined;
  pwd: string | undefined;
}

let u = new User();
u.name = 'jack';
u.pwd ='sssss';
//  将类作为泛型的类型校验
let oMysql = new MysqlDb();
let oMssql = new Mssql();
oMysql.add(u)
oMssql.add(u)

命名空间

namespace

装饰器

通俗的讲装饰器就是一个方法,可以注入到类,方法,属性或参数上来拓展类,属性,方法和参数的功能。

类装饰器

  1. 类装饰器--不传参
function logClass(params:any) {
  // params:当前的类
  params.prototype.apiUrl = '动态拓展的属性'
  params.prototype.run = function() {
    console.log('一个方法')
  }
}

@logClass
class Http {
  constructor () {}
  getData () {}
}

let httpClient:any = new Http();
console.log(httpClient.apiUrl) => '动态拓展的属性'

httpClient.run()

  1. 类装饰器--接受传参 (装饰器工厂)
function logClass(params:string) {
  // params:当前的类
  return function (target:any) {
    console.log(target)
    console.log(params)

    target.prototype.apiUrl = params;
  }
}

@logClass('www.baidu.com')
class Http {
  constructor () {}
  getData () {}
}

let httpClient:any = new Http();
  1. 重载构造函数
function logClass(target: any) {
  return class extends target {
    name:any = '修改后的name';
    getData () {
     this.name = this.name + '----'
    }
  }
}

@logClass
class Http {
  public name:string|undefined
  constructor () {
    this.name = 'name 1'
  }
  getData () {
    console.log(this.name)
  }
}

let httpClient:any = new Http();
httpClient.getData()

属性装饰器

属性装饰器表达式会在运行时当做函数被调用,传入下列两个参数

  1. 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
  2. 成员的名字
function logProperty(params:string) {
  return function (target: any,attr: any) {
    // 这里target 及 attr 分别是构造函数和修饰的属性
    console.log(target, attr)
    target[attr] = params // 修改为穿过来的参数
  }
}

class Http {
  @logProperty('name 2')
  public name:string|undefined
  constructor () {
    this.name = 'name 1'
  }
  getData () {
    console.log(this.name)
  }
}

let httpClient:any = new Http();
httpClient.getData()

方法装饰器

会被应用到方法的属性描述上 可以用来监视 修改或者替换方法定义
运行时回传入下列3个参数

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
  • 成员的名字
  • 成员的属性描述符

方法参数装饰器

会在运行时当做函数被调用,可以使用参数装饰器为类的原型增加一些元素数据
传入下列三个参数

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
  • 成员的名字
  • 参数在函数参数列表中的索引

你可能感兴趣的:(TypeScript学习笔记)