一般,经常使用的声明文件,社区都帮咱们作好了。在此做为笔记分享,仍是要了解下当第三方库没有时,本身该如何书写。在动手前,先分析下场景:javascript
<script>
引入,注入全局变量 xxx
;npm install @types/xxx --save-dev
安装,不准任何配置;xxx.d.ts
存放当前项目中,建议和其余 *.ts
都存放在 src 目录下(没有生效,可检查 tsconfig.json
中的 file、include、exclude
等配置);声明语句 | 含义 | 举例 |
---|---|---|
declare var 、declare const 、declare let |
声明 全局变量 | declareVar.ts |
declare function |
声明 全局方法 | declareFunction.ts |
declare class |
声明 全局类 | declareClass.ts |
declare enum |
声明 全局枚举类型 | declareEnum.ts |
declare namespace |
声明 全局对象 | declareNamespace.ts |
interface 、type |
声明 全局类型 | declareInterface.ts 和 declareType.ts |
declare var
、declare const
、declare let
// jQuery2.d.ts
declare const jQuery2: (selector: string) => any;
复制代码
// declareVar2.ts
jQuery2('#root');
复制代码
declare function
// declareFunction.d.ts
declare function declareFunc(selector: string): any;
复制代码
// declareFunction.ts
declareFunc('#root');
复制代码
declare class
// declareClass.d.ts
declare class DeclareClass {
name: string;
constructor(name: string);
showName(): string;
showName2() {
return `我是${this.name}`;
}
}
// 0.1.3/declareClass.d.ts:5:17 - error TS1183: An implementation cannot be declared in ambient contexts.
// 5 showName2() {
复制代码
// declareClass.ts
let declareClass = new DeclareClass('class');
复制代码
declare class
只定义类型,不具体实现( 例子中 showName2
是具体实现因此报错了)。java
declare enum
// declareEnum.d.ts
declare enum DeclareEnum {
man,
woman
}
复制代码
// declareEnum.d.ts
let person = [ DeclareEnum.woman, DeclareEnum.man ];
复制代码
declare namespace
namespace
第一次见,是 ts 早期为了解决模块化造的关键字,顾名思义是命名空间的意思。node
由来:前面说了 ts 用
namespace
解决模块化,那模块化单词是module
,可后来 ES6 也是用了module
,因为 ts 要兼容 ES6,不得已将module
改成namespace
。git
不建议用:ES6 的出现,ts 不建议再用
namespace
来解决模块化问题,而是推荐使用 ES6 的模块化方案(ts 仍是很包容的,一切为了程序员的便利)。程序员
了解其原理:虽然
namespace
不建议用了,但declare namespace
仍是经常使用的,表示全局变量的一个对象,因此就有子属性。github
// declareNamespace.d.ts
declare namespace declareNamespace {
const name: string;
function showName(name: string): void;
class Gender {
showGender(gender: string): void;
}
enum Direction { up, right, down, left }
namespace ns {
function showNs(name: string): void;
}
}
复制代码
// declareNamespace.ts
declareNamespace.showName('declareNamespace');
declareNamespace.ns.showNs('ns');
复制代码
注:在声明对象中可继续嵌入声明对象。typescript
interface
和 type
// interface.d.ts
interface Options {
position?: 'TOP' | 'BOTTOM';
data?: any;
}
declare namespace modal {
function open(title: string, options?: Options): void;
}
复制代码
// interface.ts
let options: Options = {
position: 'top',
data: {
width: 200
}
}
modal.open('新增', options);
复制代码
上面 interface
没什么问题,可是它是暴露在全局类型中的,因此最好存放在 namespace
中,可改写为npm
// interface2.d.ts
declare namespace modal {
interface Options {
position?: 'top' | 'bottom';
data?: any;
}
function open(title: string, options?: Options): void;
}
复制代码
// interface2.ts
let options: modal.Options = {
position: 'top',
data: {
width: 200
}
}
modal.open('新增', options);
复制代码
经过 import xxx from 'xxx'
导入,符合 ES6 模块规范。知道怎么引入 npm 包,还得知道怎么去建立 npm 包。json
场景是当接手一个项目,一是查找其 npm 包可看 package.json
中的 types
,二是查看有无 xxx/index.d.ts
声明文件。为了便于本身和他人,请将声明文件和 npm 包绑定在一块儿(若是之后本身发布 npm 包)。模块化
@types
(没有和 npm 包绑定在一块儿,由其余人发布)因为种种状况,有的 npm 包并无声明文件,这个时候试着安装 xxx(npm install @types/xxx -S
)来判断 @types
是否存在声明文件(为了在 ts 便利使用,其余人补足了对应的声明文件,但只能发布到 @types
里)。
一是建立在 node_modules/@types/xxx/index.d.ts
,这种方式不须要额外配置(好处),可是 node_modules
是不稳定的,由于 node_modules
目录不会发布到仓库、没法版本回溯、有删除风险、多人团队应用乱等问题,因此不建议使用;二是建立 types
目录,专门存放本身写的声明文件,如 @types/xxx/index.d.ts
,此刻须要 tsconfig.json
配合,成功规避掉第一种方法产生的问题;
project
├── src
| └── index.ts
├── types
| └── xxx
| └── index.d.ts
└── tsconfig.json
复制代码
tsconfig.json
内容{
"compilerOptions": {
"module": "commonjs",
"baseUrl": "./",
"paths": {
"*": ["types/*"]
}
}
}
复制代码
语法 | 含义 | 示例 |
---|---|---|
export | 导出变量 | types/export/index.d.ts 和 0.1.3/export.ts |
export namespace | 导出对象(含子属性) | types/export/index.d.ts 和 0.1.3/export.ts |
export default | 导出默认(ES6)(推荐) | types/exportDefault/*.d.ts 和 0.1.3/exportDefault.ts |
export = commonjs | 导出模块(不推荐) |
export
导出变量前面谈到过全局变量的声明文件方式,npm 包声明文件和其有必定区别。
declare
声明全局变量,就只是声明一个普通变量(局部变量);export
导出;import
导入而后使用,这个和 ES6 同样(无学习成本);下面就本身建立声明文件,推荐写在 types
目录下,后续也是如此。
// types/export/index.d.ts
export const name: string;
export function showName(): string;
export class Star {
constructor(name: string);
say(): string;
}
export enum Gender {
woman,
man
}
export interface Options {
position?: 'TOP' | 'BOTTOM';
data?: any;
}
export namespace declareNamespace {
const name: string;
namespace ns {
function showNs(name: string): string;
}
}
复制代码
// 0.1.3/export.ts
import { name, showName, Star, Gender, Options, declareNamespace } from '../types/export';
console.log(name);
let myName = showName();
let newStar = new Star('pr');
let gender = [Gender.woman, Gender.man];
let options: Options = {
position: 'TOP',
data: { name: 'pr', age: 18 }
}
console.log(declareNamespace.name);
declareNamespace.ns.showNs('ns');
复制代码
export default
导出默认(ES6)export default
不管是 ES6 仍是 Typescript 都是直接默认导出。在 Typescript 中可直接导出 function
、class
和 interface
。
// types/exportDefault/function.d.ts
export default function showName(): string;
复制代码
// types/exportDefault/class.d.ts
export default class Star {
constructor(name: string);
say(): string;
}
复制代码
// types/exportDefault/interface.d.ts
export default interface Options {
position?: 'TOP' | 'BOTTOM';
data?: any;
}
复制代码
// types/exportDefault/enum.d.ts
declare enum Gender {
woman,
man
}
export default Gender;
复制代码
// types/exportDefault/namespace.d.ts
declare namespace declareNamespace {
const name: string;
namespace ns {
function showNs(name: string): string;
}
}
export default declareNamespace;
复制代码
export =
导出模块commonjs 规范中,导出一个模块能够
// 导出总体
module.exports = xxx;
// 导出单个
exports.xxx = xxx;
复制代码
在 Typescript 中,对于 commonjs 模块导出,有多种导入方式
// 导入总体
const xxx = require('xxx');
import * as xxx from 'xxx';
import xxx = require('xxx');
// 导入单个
const fn = require('xxx').fn;
import { fn } from 'xxx';
import fn = xxx.fn;
复制代码
注:
import ... require
和export =
都是 Typescript 为了兼容 AMD 规范和 commonjs 规范建立的语法,因为不经常使用因此也不推荐用。而是推荐使用 ES6 标准的export default
和export
(你们都这么用)。
通用模块定义(Universal Module Definition),UMD 库指那些能够经过 <script>
标签引入,又能够经过 import
导入的库。和 npm 包的声明文件不一样的是,须要额外声明一个全局变量。
// types/umd/index.d.ts
export as namespace umd;
export default umd;
// export = umd;
declare function umd(): string;
declare namespace umd {
let ns: string;
function showNs(ns: number): string;
}
复制代码
// 0.1.3/umd.ts
import umd from '../types/umd';
umd();
umd.ns = '18';
umd.showNs(18);
复制代码