当使用第三方库时,需要引用其声明文件,才能获得对应的代码补全、接口提示等功能

如果想在ts里使用jQuery,需要使用声明语句先声明

  1. jQuery('#foo') // ERROR: Cannot find name 'jQuery'.
  2. // 但在ts中,编译器并不知道 $ 或 jQuery是什么
  3. // 需要使用declare var来定义其类型
  4. declare var jQuery: (selector: string) => any;
  5. jQuery('#foo')

declare var 并没有真正定义一个变量,只是定义了类型,编译结果会删除

什么是声明文件

通常会把声明语句放到单独的一个文件(比如jQuery.d.ts)中,这就是声明文件,声明文件必须以.d.ts为后缀

  1. // src/jQuery.d.ts
  2. declare var jQuery: (selector: string) => any;
  3. // src/index.ts
  4. jQuery('#foo')

当把jQuery.d.ts 放到项目中时,其他所有*.ts文件就都可以获得jQuery的类型定义了,如果还是无法解析,可以检查下
tsconfig.json 中的 files、includes、exclude 配置,看是否包含了jQuery.d.ts文件

  1. /path/to/project
  2. ├── src
  3. | ├── index.ts
  4. | └── jQuery.d.ts
  5. └── tsconfig.json

第三方声明文件

社区定义好了很多声明文件,可以下载下来使用即可,推荐使用 @types 统一管理第三方库的声明文件,使用方法如下

  1. npm install @types/jquery --save-dev

搜索需要声明的文件 https://microsoft.github.io/TypeSearch/

书写声明文件

当第三方库没有提供声明文件时,就需要自己手写声明文件了。不同的使用场景,声明文件的内容和使用方法会有所区别

全局变量

  1. // 1.declare var 声明全局变量, 可以是 declare let , declare const ,const无法修改,其他可修改
  2. // 注意不要在声明语句中,定义具体的实现
  3. // src/jQuery.d.ts
  4. declare let jQuery: (selector: string) => any;
  5. // 2.declare function,支持函数重载
  6. declare function jQuery(selector: string): any;
  7. declare function jQuery(domReadyCallback: () => any): any;
  8. // 3.declare class
  9. declare class Animal {
  10. name: string;
  11. constructor(name: string);
  12. sayHi(): string; // 不能有具体实现,否则会报错
  13. }
  14. // 4.declare enum
  15. declare enum Directions {
  16. Up,
  17. Down,
  18. Left,
  19. Right
  20. }
  21. // 5.declare namespace
  22. // 随着es6广泛应用,已经**不建议再使用ts中的namespace**,直接使用es6的模块化方案
  23. declare namespace jQuery {
  24. function ajax(url: string, settings?: any): void;
  25. const version: number;
  26. class Event {
  27. blur(eventType: EventType): void
  28. }
  29. enum EventType {
  30. CustomClick
  31. }
  32. }
  33. // 嵌套命名空间
  34. jQuery.ajax('/api/get_something');
  35. jQuery.fn.extend({
  36. check: function() {
  37. return this.each(function() {
  38. this.checked = true;
  39. });
  40. }
  41. });
  42. // 6.interface和type
  43. interface AjaxSettings {
  44. method?: 'GET' | 'POST'
  45. data?: any;
  46. }
  47. declare namespace jQuery {
  48. function ajax(url: string, settings?: AjaxSettings): void;
  49. }

npm 包

一般通过 import foo from 'foo' 导入一个npm包

在导入npm包前,需要看看声明文件是否存在,一般声明文件可能存放在下面两个地方:

  1. 与该npm包绑定在一起,判断package.json中是否有types字段,或者有一个index.d.ts声明文件,这样不需要额外安装其他包,最推荐。
  2. 发布到 @types 里,安装 npm install @types/foo --save-dev

如果没有声明文件,就需要自己写声明文件了,具体方法参见: https://ts.xcatliu.com/basics/declaration-files#npm-bao

npm包的声明文件与全局变量的声明文件有很大区别。使用declare不会声明全局变量,只会声明一个局部变量,只有要陪你过export导出,再用import导入,才可以

  1. // 1. export 导出变量
  2. export const name: string;
  3. export function getName(): string;
  4. export class Animal {
  5. constructor(name: string);
  6. sayHi(): string;
  7. }
  8. export enum Directions {
  9. Up,
  10. Down,
  11. Left,
  12. Right
  13. }
  14. export interface Options {
  15. data: any;
  16. }
  17. // 混用declare与export
  18. declare const name: string;
  19. declare function getName(): string;
  20. declare class Animal {
  21. constructor(name: string);
  22. sayHi(): string;
  23. }
  24. declare enum Directions {
  25. Up,
  26. Down,
  27. Left,
  28. Right
  29. }
  30. interface Options { // interface前不需要declare
  31. data: any;
  32. }
  33. export { name, getName, Animal, Directions, Options };
  34. // 2.export default,只有 function、class、interface 可以直接默认导出,其他变量需要先定义出来,再导出
  35. export default function foo(): string;
  36. // 3.export =
  37. export = foo;
  38. declare function foo(): string;
  39. declare namespace foo {
  40. const bar: number;
  41. }

其他

UMD库、直接扩展全局变量、在npm包或UMD库中扩展全局变量、模块插件、发布声明文件 参见: 声明文件 - TypeScript 入门教程