ts学习之路

218 阅读5分钟

TypeScript

不要问为什么要学它。直接开干

安装(不需要本地运行*.ts文件的可以不装)

全局安装typescript:npm i -g typescript
编译:tsc *.ts
注意:使用tsc命令编译ts文件后,会生成一个.js的文件*

vscode配置ts

  1. 执行tsc --init生成tsconfig.json配置文件
  2. 菜单选择:终端=>运行任务=>监视tsconfig.json

ts数据类型

  • 布尔类型 boolean

  • 数字 number

  • 字符串 string

  • 数组 array

    let arr:number[] = [1,2,3]
        或
    let arr:Array<number> = [1,2,3]
    
  • 元祖 tuple

    let arr:[number,string] = [1,'2'] // 定义几个类型就要初始化几个值,一一对应
    
  • 枚举 enum

    enum sexType {
        f=1,
        m=2
    }
    let a:sexType = sexType.f
    console.log(a) // 1
    
    enum Types {'undefined'=-1,'null'=2,'success'=0}
    let e:Types = Types.null
    console.log(e) // 2
    

    注意:

    1. 如果标识符没有赋值,那么value就是他的索引值;
    2. 如果其中某一个定义了number类型的value,后续的索引都在这个基础上递增;
  • 任意类型 any

    let box:any = document.getElementById('box');
    box.style.color = 'red';
    
  • nullundefined

  • void(一般用于定义方法的返回值)function run():void{}

  • never 不会出现的类型(包括null、undefined)的子类型

    let a:never = (()=>{ throw new Error('异常')})()
    

函数定义

参考:TS之函数详解

  • 参数要有类型,可配置默认值,可配置可选参数
  • 剩余参数
  • 函数要有返回值
  • 函数可以重载
// 函数创建和声明的两种方式
// 1.关键字
function fn1(a: string): string {
    return ''
}

// 2.函数表达式
let fn2: (a: string) => string = function (a) {
    return ''
}

// type
type callback = (a: string) => string;
// interface
interface ICallback {
    (a: string): string;
}

let fn3: callback = function (a) { return '' }
let fn4: ICallback = function (a) { return '' }

// 默认参数、可选参数
function getInfo(name: String,isOk:Boolean = false,sex?:String):void {}
// 剩余参数
function getInfo(name: String,...result:String[]):void {}
// 函数重载
function getData(id: String): void {
  console.log('方法0:', id);
}
function getData(param: String): void {
  console.log('方法一:', param);
}
getData('2'); //如果没有下面的方法则输出: 方法一: 2  反之 方法二: 2 -- undefined

function getData(param: String, id?: String): String {
  console.log('方法二:', param, '--', id);
  return '2';
}
getData('1'); // 方法二: 1 -- undefined
function getData():void {}

类(构造函数)

image.png

继承

function User(name){
    this.name =name    
}

User.prototype.run=function(){
    return this.name+'1234567890'
}

// 1.对象冒充继承。 无法继承原型链上的方法
function Web(name){
    User.call(this,name)
}

// 2.原型链继承,无法在初始话的时候传值
function Web(){}
Web.prototype  = new User() 

// 3. 对象冒充继承+原型链继承,完美解决上面两种问题
function Web(name){
    User.call(this,name) // 对象冒充继承
}
Web.prototype  = User.prototype


let b = new Web('你好')
// console.log(Web.prototype)
console.log(b.name)
console.log(b.run())

ES6以后的实现

  class Person {
    // public 共有属性
    public love: String = '爱';
    // private 只能在当前类里面进行访问
    private nick: String;
    // protected 保护类型 外部无法访问,子类能访问
    protected who: String = '你谁啊';

    name: String; // 默认就是 public
    constructor(name: String) {
      this.name = name;
      this.nick = name;
    }

    gitinfo() {
      return `${this.nick}`;
    }
  }
  class Web extends Person {
    content: String;
    constructor(name: String, content: String) {
      super(name);
      this.content = content;
    }

    workSome() {
      return `${this.name}${this.content},${this.who}`;
    }
    // 静态方法,无法访问定义当前类属性。this指向当前这个函数
    static work() {
      return `${this.name}`;
    }
  }
  const my = new Person('张三');
  const some = new Web(my.name, '你去做饭吧');
  console.log(some.workSome()); // 张三你去做饭吧,你谁啊
  console.log(Web.work()); // Web

declare 声明

  • 对第三方类型进行扩展(如Uni)
// / <reference types="vite/client" />

declare module '*.vue' {
  import { DefineComponent } from 'vue'
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
  const component: DefineComponent<{}, {}, any>
  export default component
}

declare module 'uview-ui'

/* eslint-disable @typescript-eslint/no-explicit-any */
import Jsbridge from './util/flutterBridge'

declare global {
  interface Window {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    $flutter: typeof Jsbridge
    _aMap: any
    spBridge: any
    NoCaptcha: any
    [key: string]: any
  }
  // 类型融合,解决对uni的扩展
  interface Uni {
    $api: any
    $util: any
    $local: any
  }
}

export {}

abstract抽象类(定义标准)

  • 抽象类是提供给其他类继承的基类,不能被直接实例化
  • 用abstract关键字定义的抽象类中的方法,不需要实现,但是在子类中必须实现
  • abstract 关键字只能出现在抽象类中
abstract class Ren {
    abstract eat(): any;
  }
  class Person extends Ren {
    constructor(name: String) {
      super();
    }
    // 抽象类的抽象方法必须在子类进行实现,孙子类可以不实现
    eat() {
      return '吃东西';
    }
  }

interface接口,定义约束规范

  • 接口中的字段以;结尾
  • interface 可以约束定义属性对象。但是属性值必须一一对应,不能多字段或者少字段;

属性类型的接口

interface ParamObj {
    label: String;
    value?: Number;
    // name: String = 'interface';  不能初始化值
  }
  function printLabel(param: ParamObj) {
    console.log('输出:', param.label);
  }
  printLabel({ label: '你好ts' });
  printLabel({ label: '你好ts', value: 2 });

函数类型的接口

  • 参数必须由()包裹起来
// 例子:一
  interface FnTyoe {
    (id: String, type: Number): String;
  }

  const fn: FnTyoe = function (id: String, type: Number) {
    console.log('输出:', type);
    return id;
  };
  fn('你好ts', 2);
  // 例子:二
  interface ParamObj {
    id: String;
    type: Number;
  }
  interface FnObjTyoe {
    (param: ParamObj): String;
  }
  const fn1: FnObjTyoe = function (param: ParamObj) {
    console.log('输出:', param.type);
    return param.id;
  };

  fn1({ id: '你好ts', type: 2 });

数组、对象类型的接口

  • key||index 必须由[]包裹起来
// 例子:一
  interface StrArr {
    [index: number]: String;
  }
  const arr: StrArr = ['1', '2'];
  // const arr: StrArr = ['1', 2]; ❌
  console.log(arr);
  // 例子:二
  const obj: StrArr = { 1: '1' };
  // const obj: StrArr = { 1: '1', 2: 2 }; ❌
  console.log(obj);

类型的接口

  • 使用关键字implements
  • 按照接口规范必须定义相应的属性函数
// 例子:一
  interface Ren {
    name: String;
    age?: String;
    eat(value: String): void;
  }

  class Person implements Ren {
    name: String; // 必须实现 ✅
    sex: String;
    constructor(name: string) {
      this.name = name;
      this.sex = '男';
    }
    // eat 必须实现 ✅
    eat() {
      console.log(this.name + '吃吧!');
    }
  }
  const a = new Person('张三');
  a.eat();

interface的扩展||继承

  • 使用extends来做继承
// 例子:一
  interface Animal {
    age: Number;
    eat(): void;
  }
  interface Ren extends Animal {
    name: String;
    work(): void;
  }
  class Web {
    name: String;
    constructor(name: string) {
      this.name = name;
    }
    coding() {
      console.log(this.name, '写代码');
    }
  }
  class Person extends Web implements Ren {
    name: String; // 必须实现 ✅
    sex: String;
    age: Number; // 必须实现 ✅
    constructor(name: string, age: Number) {
      super(name);
      this.age = age;
      this.name = name;
      this.sex = '男';
    }
    // eat 必须实现 ✅
    eat() {
      console.log(this.name + '吃吧!');
    }
    // eat 必须实现 ✅
    work() {
      console.log(this.name + '好好干');
    }
  }

  const a = new Person('张三', 22);
  a.eat();
  a.coding();

T泛型(可以不用T用其他也行)

  • 定义一个不特定的类型

函数泛型

// 例子:一
  function getData<Z>(value: Z): Z {
    return value;
  }

  getData<String>('abc');
  // getData<String>(1234567);❌
  getData({ key: 111 }); // 不写类型相当于any

类泛型

这里的T代表下面的T都是泛型

// 例子一
 class Peron<T> {
    arr: T[] = [];
    add(value: T) {
      this.arr.push(value);
    }
    getArr(): T[] {
      return this.arr;
    }
  }
  const a = new Peron<String>();
  a.add('1');
  // a.add(12345); ❌   初始化 const a = new Peron<String | Number>();才能传入数字
  const aa = a.getArr();
  console.log(aa);
 // 例子二
 class User {
    name: String;
    sex: String;
    constructor(name: String) {
      this.name = name;
      this.sex = '男';
    }
  }
  const b = new Peron<User>();
  // b.add('111'); ❌
  b.add(new User('张三'));
  

泛型接口interface

// 例子一
interface FnType {
<T>(value: T): T;
}
const fn: FnType = function (value: T): T {
return value;
};
fn<String>('abc');
// fn<String>(12345); ❌
// 例子二
interface FnType1<T> {
(value: T): T;
}

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

const fn1: FnType1<Number> = getData;
// fn1('ddd');❌
fn1(123);

例子二

  interface ObjType<T> {
    addUser(id: T): Boolean;
    getInfo(param: Number): T;
  }
  class User {
    name: String;
    age: Number;
    constructor(name: String, age: Number) {
      this.name = name;
      this.age = age;
    }
  }

  class SchoolUser {
    name: String;
    age: Number;
    sex: String;
    constructor(name: String, age: Number) {
      this.name = name;
      this.age = age;
      this.sex = '男';
    }
  }

  class School<T> implements ObjType<User> {
    name: String;
    users: User[];
    constructor(name: String) {
      this.name = name;
      this.users = [];
    }

    addUser(value: User) {
      this.users.push(value);
      return true;
    }
    getInfo(age: Number) {
      let result;
      this.users.forEach((e: User) => {
        if (e.age === age) result = e;
      });
      return result;
    }

    update(value: T) {
      console.log(value);
      return true;
    }
  }

  const a = new School<SchoolUser>('秦岭学校');
  const u = new User('张三', 22);
  const u1 = new SchoolUser('李四', 23);
  a.addUser(u);
  // a.update(u); ❌
  a.update(u1);
  console.log(a.getInfo(22)); // User {name: '张三', age: 22}