TypeScript:3月份ts学习笔记整合

各种各样的类型

基础类型:  number   string   null   undefined   symbol   boolean   void空

对象类型: {}   Class   function []

const teacher: {
  name: string;
  age: number;
} = {
  name: "Dell",
  age: 18
};
const numbers: number[] = [1, 2, 3];
class Person {}
const my: Person = new Person();
const getNumber: () => number = () => {
  return 123;
};

枚举类 对应的值默认从0开始 可以手动赋值

enum Status {
  OFFLINE,
  ONLINE,
  DELETED
}
console.log(Status.OFFLINE);
console.log(Status[0]);
function getResult(status) {
  if (status === Status.OFFLINE) {
    return "offline";
  } else if (status === Status.ONLINE) {
    return "online";
  } else if (status === Status.DELETED) {
    return "deleted";
  } else {
    return "error";
  }
}
let result = getResult(Status.OFFLINE);
console.log(result);

never: 永远不会执行完函数

function errorEmitter(): never {
  throw new Error();
}
function whileEmitter(): never {
  while (true) {}
}

数组:

const numberArr: number[] = [1, 2, 3];
const arr: (number | string)[] = [1, "2", "3"];
const objectArr: { name: string }[] = [{ name: "1" }, { name: "2" }];

元组:

const teacherInfo: [string, string, number] = ["yh", "nv", 10];
const teacherList: [string, number][] = [
  ["yh", 10],
  ["hy", 20]
];

type  alias 类型别名:

type User = { name: string; age: number };
const objArr: User[] = [
  { name: "1", age: 10 },
  { name: "2", age: 11 }
];
class Teacher {
  name: string;
  age: number;
}
const objArr1: Teacher[] = [
  new Teacher(),
  {
    name: "h",
    age: 10
  }
];

type  annotation 类型注解 我们来告诉ts变量类型

type  inference 类型推断 ts自动尝试分析变量类型


接口、类、继承

接口:

interface Person {
  //readonly name: string; //修饰符只读不能赋值
  name: string;
  age?: number; //加一个?表示可有可无
  [propName: string]: any; //可以传 名字为字符串 值为任何类型
  //say(): string;
}
const getName = (person: Person) => {
  console.log(person.name);
};
getName({ name: "yh" });
class Users implements Person {
  //在类里用接口
  name = "yh";
  // say() {
  //   return "hello";
  // }
}
interface Study extends Person {
  //接口继承
  // hight: string;
}

类继承:

class Persons {
  name: string = "yh";
  getName() {
    return this.name;
  }
}
//类继承 Teachers是子类  Persons是父类
class Teachers extends Persons {
  getTeacherName() {
    return "teacher";
  }
  getName() {
    //super.getName(); 调用父类方法
    return super.getName() + "覆盖父类getName方法";
  }
}
const person = new Persons();
console.log(person.getName()); //直接运行ts代码 ts-node type2.ts
const teacher = new Teachers();
console.log(teacher.getName());

访问类型: private允许在类内调用 protected允许在类内及继承的子类中使用 public允许在类的内外调用

 public name: string;
  //private name: string;
  //protected name:string;
  sayHi() {
    console.log("111");
  }
}

类构造器: constructor

class Person3 {
  // public name: string;
  // constructor(name: string) {
  //   this.name = name;
  // }
  constructor(public name: string) {}
}
const person3 = new Person3("yh");
console.log(person3.name);
class Teacher3 extends Person3 {
  constructor(age: number) {
    super("yh"); //子类用构造器需调用父类构造器
  }
}
const teacher3 = new Teacher3(28);

get  set:

class Person4 {
  constructor(private _name: string) {}
  get name() {
    return this._name;
  }
  set name(name: string) {
    this._name = name;
  }
}
const person4 = new Person4("yh");
console.log(person4.name);
person4.name = "yh"; //赋值

构建一个单例:

class Demo {
  private static instance: Demo;
  private constructor() {}
  static getInstance() {
    if (!this.instance) {
      this.instance = new Demo();
    }
    return this.instance;
  }
}
const demo1 = Demo.getInstance();

抽象类: 抽象方法 把公用的东西抽象出来

abstract class Geom {
  width: number;
  getType() {
    return "Geom";
  }
  abstract getArea(): number;
}
class Circle extends Geom {
  getArea() {
    return 123;
  }
}
class Square extends Geom {
  getArea() {
    return 456;
  }
}

抽象接口:

interface Person6 {
  name: string;
}
interface teacher6 extends Person6 {}
interface stydent extends Person6 {
  age: number;
}
const teacher6 = {
  name: "yh"
};
const stydent = {
  name: "hy",
  age: 18
};
const getUserInfo = (user: Person6) => {
  console.log(user.name);
};
getUserInfo(stydent);

联合类型+类型保护

联合类型:

interface Bird {
  fly: boolean;
  sing: () => {};
}
interface Dog {
  fly: boolean;
  bark: () => {};
}

类型保护:

//类型断言方式 as语法
function canDo(animal: Bird | Dog) {
  if (animal.fly) {
    (animal as Bird).sing();
  } else {
    (animal as Dog).bark();
  }
}
//in 语法
function cantDo(animal: Bird | Dog) {
  if ("sing" in animal) {
    animal.sing();
  } else {
    animal.bark();
  }
}
//typeof 语法
function add(first: string | number, second: string | number) {
  if (typeof first === "string" || typeof second === "string") {
    return `${first}${second}`;
  }
  return first + second;
}
//instanceof 语法  不能用interface
class NumberObj {
  count: number;
}
function addSecond(first: object | NumberObj, second: object | NumberObj) {
  if (first instanceof NumberObj && second instanceof NumberObj) {
    return first.count + second.count;
  } else {
    return 0;
  }
}

泛型

泛型是指—–generic 泛指的类型 调用时指定类型

function join<T>(first: T, second: T): T {
  return first;
}
join<string>("1", "123");

数组泛型 T[]

function map<T>(params: Array<T>) {
  return params;
}
map<string>(["123"]);

多个泛型

function add<T, P>(first: T, second: P) {
  return `${first}+${second}`;
}
add<number, string>(1, "11");

类中泛型

class DataManager<T> {
  constructor(private data: T[]) {}
  getItem(index: number): T {
      return this.data[index];
  }
}
const data = new DataManager<number>([1, 2]);
data.getItem(0);

泛型继承

interface Item {
  name: string;
}
class DataManager1<T extends Item> {
  constructor(private data: T[]) {}
  getItem(index: number): string {
    return this.data[index].name;
  }
}
const data1 = new DataManager1([{ name: "dd" }]);

使用泛型作为一个具体的类型注解

const funcs: <T>() => string = <T>() => {
  return "123";
};

function hello<T>(param: T) {
  return param;
}
const func: <T>(param: T) => T = hello;

泛型中使用keyof语法

interface Person {
  name: string;
  age: number;
}
class Teacher {
  constructor(private info: Person) {}
  //循环Person -> T的类型为string ->返回类型为T的类型
  getInfo<T extends keyof Person>(key: T): Person[T] {
    return this.info[key];
  }
}
const teacher = new Teacher({
  name: "dell",
  age: 18
});
const test = teacher.getInfo("name");
console.log(test);

namespace命名空间

在ts中初步的模块化思想就是namespace(命名空间)

//编译后只生成一个变量
namespace Home {
  class Header {
    constructor() {
      const elem = document.createElement("div");
      elem.innerText = "Header";
      document.body.appendChild(elem);
    }
  }
  class Content {
    constructor() {
      const elem = document.createElement("div");
      elem.innerText = "Content";
      document.body.appendChild(elem);
    }
  }
  //只暴露这一个类
  export class Page {
    constructor() {
      new Header();
      new Content();
    }
  }
  //定义接口
  export interface Uset{
    name:string
  }
  //定义子空间
  export namespace childHome Uset{
    export class Test{}
  }
}

两个ts文件中命名空间相互引用时,会使用依赖声明来标注

声明方式:///<reference path=’./components.ts’/>


.d.ts注解文件

ts里有一种独特的文件,以.d.ts结尾,这种文件叫做类型描述文件。注解文件通常使用declare关键字描述类型

这里以jquery为例,现在想在ts文件种使用jq的方法,如下:

//import $ from "jquery"; //es6引入jq模块包 这里的引用名字和注解文件里的名字要相同
$(function() {
  $("body").html("123");
  new $.fn.init();
});

这时需要创建一个jquery.d.ts文件帮助ts理解jq,分为两种情况,外部引入jq和Es6引入jq模块包

第一种   (外部引入jq.js文件)

函数重载:声明 -> $的类型是函数,接收函数,返回值是空

interface JqueryInstance {
  html: (html: string) => {};
}
declare function $(readyFunc: () => void): void;
declare function $(selector: string): JqueryInstance;
//对类和对象进行类型定义,命名空间嵌套
declare namespace $ {
  namespace fn {
    class init {}
  }
}

interface的方式实现函数重载

interface JQuery {
  (readyFunc: () => void): void;
  (selector: string): JqueryInstance;
}
declare var $: JQuery;

第二种(Es6引入jq模块包)

Es6模块化必须要添加注解  module后的名字和引用的名字一样

declare module "jquery" {
  interface JqueryInstance {
    html: (html: string) => {};
  }
  //混合类型
  function $(readyFunc: () => void): void;
  function $(selector: string): JqueryInstance;
  namespace $ {
    namespace fn {
      class init {}
    }
  }
  export = $;
}

奇奇怪怪的装饰器

学习准备装饰器是实验性特性,未来可能会不是这种用法

现在想要使用需要在tsconfig.json文件中打开这两个注释,否则使用装饰器会报错

装饰器本身是一个函数 通过@符号使用

类的装饰器

接收的参数是类的构造函数    创建类后立即执行

多个装饰器执行时  从下到上执行

function testDecorator(constructor: any) {
  //在类上创建getName方法
  constructor.prototype.getName = () => {
    console.log("dell");
  };
}
function testDecorator1(constructor: any) {
  console.log("先执行");
}
//多个装饰器执行时 从下到上执行
@testDecorator
@testDecorator1
class Test {}
const test = new Test();
(test as any).getName();
//对装饰器进行 工厂函数包装
function testDecorator2(flag: boolean) {
  if (flag) {
    return function(constructor: any) {
      constructor.prototype.getName = () => {
        console.log("dell");
      };
    };
  } else {
    return function(constructor: any) {};
  }
}
@testDecorator2(true)
class Test2 {}
const test2 = new Test2();
//(test2 as any).getName();
//new (...args: any[])=> {} 这是一个构造函数 接收很多都是any类型的参数 返回很多any类型的值
function testDecorator3<T extends new (...args: any[]) => {}>(constructor: T) {
  //对类里的构造函数做扩展 会先执行原来的构造函数
  return class extends constructor {
    name = "lee";
    getName() {
      return this.name;
    }
  };
}
@testDecorator3
class Test3 {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}
const test3 = new Test3("dell");
//工厂模式 ->识别装饰器中新增的类方法
function testDecorator4() {
  return function<T extends new (...args: any[]) => {}>(constructor: T) {
    //对类里的构造函数做扩展 会先执行原来的构造函数
    return class extends constructor {
      name = "lee";
      getName() {
        return this.name;
      }
    };
  };
}
const Test4 = testDecorator4()(
  class {
    name: string;
    constructor(name: string) {
      this.name = name;
    }
  }
);
const test4 = new Test4("dell");
test4.getName();

方法装饰器

普通方法接收的参数:target对应类的prototype原型,key对应装饰函数的名字,descriptor设置方法的属性

静态方法接收的参数:target对应类的构造函数

function getNameDecorator(
  target: any,
  key: string,
  descriptor: PropertyDescriptor
) {
  //此函数是否可以在外部再次修改
  descriptor.writable = false;
  //对方法的内容做变更
  descriptor.value = function() {
    return "Decorator";
  };
}
class Func {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  //普通方法
  @getNameDecorator
  getName() {
    return this.name;
  }
  //静态方法
  // @getNameDecorator
  // static getName1() {
  //   return 123;
  // }
}
const func = new Func("dell");
console.log(func.getName());

访问器装饰器

function visitDecorator(
  target: any,
  key: string,
  descriptor: PropertyDescriptor
) {}
class Visit {
  private _name: string;
  constructor(name: string) {
    this._name = name;
  }
  get name() {
    return this._name;
  }
  @visitDecorator
  set name(name: string) {
    this._name = name;
  }
}
const visit = new Visit("dell");
visit.name = "1233333";
console.log(visit.name);

属性装饰器

function nameDecorator(target: any, key: string): any {
  //target[key] = 'lee';  //这里修改的使原型上的属性,不是实例上的 获取方法->(names as any).__proto__.name
  //创建一个替换name的descriptor,使name不能在外部被修改
  const descriptor: PropertyDescriptor = {
    writable: false
  };
  return descriptor;
}
class Name {
  @nameDecorator
  name = "Dell";
}
const names = new Name();
console.log(names.name);

参数装饰器

三个参数 target原型 method方法名 paramIndex参数的位置

function paramDecorator(target: any, method: string, paramIndex: number) {}
class Param {
  getInfo(name: string, @paramDecorator age: number) {
    console.log(name, age);
  }
}
const param = new Param();
param.getInfo("dell", 18);

一个装饰器的小例子

使用装饰器统一判断uesrInfo是否是 undefined

const uesrInfo: any = undefined;
function catchErroe(msg: string) {
  return function(target: any, key: string, descriptor: PropertyDescriptor) {
    const fn = descriptor.value;
    descriptor.value = function() {
      try {
        fn();
      } catch (e) {
        console.log(`${msg}有问题`);
      }
    };
  };
}
class GetInfo {
  @catchErroe("name")
  getNAme() {
    return uesrInfo.name;
  }
  @catchErroe("age")
  getAge() {
    return uesrInfo.age;
  }
}
const getInfo = new GetInfo();

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章