TypeScript语法进阶重温系列(四)

173 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

1. 命名空间-namespace

  • 命名空间给我们一种类似模块化的开发方式,把一组相关的内容封装到一起,然后对外提供统一的暴露接口。(目的:减少全局变量的声明)

page.ts

namespace Home {
  class Header {
    constructor() {
      const elem = document.createElement('div');
      elem.innerText = 'This is Header';
      document.body.appendChild(elem);
    }
  }

  class Content {
    constructor() {
      const elem = document.createElement('div');
      elem.innerText = 'This is Content';
      document.body.appendChild(elem);
    }
  }

  class Footer {
    constructor() {
      const elem = document.createElement('div');
      elem.innerText = 'This is Footer';
      document.body.appendChild(elem);
    }
  }

  export class Page {
    constructor() {
      new Header();
      new Content();
      new Footer();
    }
  }
}
  • 子命名空间的写法如下:

components.ts

///<reference path="components.ts" />  // 命名空间的依赖声明(类似注释,注意开头是///)

namespace Home {
  export namespace Dell {
    export const teacher: Components.user = {
      name: 'dell'
    };
  }
  export class Page {
    constructor() {
      new Components.Header();
      new Components.Content();
      new Components.Footer();
      new Components.Footer();
    }
  }
}

page.ts

namespace Components {
  export interface user {
    name: string;
  }

  export class Header {
    constructor() {
      const elem = document.createElement('div');
      elem.innerText = 'This is Header';
      document.body.appendChild(elem);
    }
  }

  export class Content {
    constructor() {
      const elem = document.createElement('div');
      elem.innerText = 'This is Content';
      document.body.appendChild(elem);
    }
  }

  export class Footer {
    constructor() {
      const elem = document.createElement('div');
      elem.innerText = 'This is Footer';
      document.body.appendChild(elem);
    }
  }
}

注意:在tsconfig.ts配置编译选项"outFile": "./dist/page.js"配置为编译生成一个单文件时,"module": "amd"模块化的值不能为commonjs

2. import对应的模块化-缺代码

通过import和export模块化导入导出的ts代码,经过编译后生成的js代码需要借助requirejs的CDN才能执行。【在项目中结合webpack来使用就不需要使用script标签来引入CDN】

image.png

3. 使用 Parcel 打包 TS 代码

Parcel是类似webpack的工具,但不需要配置,比较方便

  • 安装依赖:npm install parcel@next -D
  • 在package.json的scripts中添加"start": "parcel ./src/html",然后执行npm start命令即可即可自动检测并编译引入到html文件中的ts代码

4. 描述文件中的全局类型

在ts中直接引入js会报错,因此需要借助一个.d.ts翻译文件来读取js,以下为jquery的.d.ts翻译文件

jquery.d.ts

// 定义全局变量
// declare var $: (param: () => void) => void;

// 定义全局函数
interface JqueryInstance {
  html: (html: string) => {};
}

// 定义一个函数的参数类型既可以为函数类型,也可以为string类型(函数重载)
declare function $(readyFunc: () => void): void;
declare function $(selector: string): JqueryInstance;

page.ts

$(function() {
  $('body').html('<div>123</div>');
});

使用declare多次定义同一个函数,称为函数的重载

使用interface的语法,也可以实现函数重载,代码如下

image.png

书写new $.fn.init();的类型定义文件,代码如下

// 如何对对象进行类型定义,以及对类进行类型定义,以及命名空间的嵌套
declare namespace $ {
	namespace fn {
		class init {}
	}
}
$(function() {
  $('body').html('<div>123</div>');
  new $.fn.init();
});

5. 模块代码的类型描述文件

  • 安装依赖:npm install jquery --save
  • 需要写jquery的类型描述文件(.d.ts文件)才能成功导入并使用jquery

jquery.d.ts

// 以下只是es6模块化的类型定义文件,其他模块化则写法不同
declare module 'jquery' {
  interface JqueryInstance {
    html: (html: string) => JqueryInstance;
  }
  // 混合类型
  function $(readyFunc: () => void): void;
  function $(selector: string): JqueryInstance;
  namespace $ {
    namespace fn {
      class init {}
    }
  }
  export = $;
}

page.ts

import $ from 'jquery';

$(function() {
  $('body').html('<div>123</div>');
  new $.fn.init();
});

6. 泛型中keyof语法的使用

interface Person {
  name: string;
  age: number;
  gender: string;
}

// 注释只是帮助理解keyof的遍历过程
// type NAME = 'name';
// key: 'name';
// Person['name'];

// type T = 'age'
// key: 'age'
// Person['age']

// type T = 'gender'
// key: 'gender'
// Person['gender']

class Teacher {
  constructor(private info: Person) {}
  getInfo<T extends keyof Person>(key: T): Person[T] {
    return this.info[key];
  }
}

const teacher = new Teacher({
  name: 'dell',
  age: 18,
  gender: 'male'
});

const test = teacher.getInfo('name');
console.log(test);

下一篇:TypeScript高级语法重温系列(五)