一起养成写作习惯!这是我参与「掘金日新计划 · 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】
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的语法,也可以实现函数重载,代码如下
书写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);