ts声明文件

431 阅读3分钟

(一)、什么是声明文件

声明文件就是给js代码补充类型标注. 这样在ts编译环境下就不会提示js文件"缺少类型".

声明变量使用关键字declare来表示声明其后面的全局变量的类型, 比如:

// packages/global.d.ts
declare var __DEV__: boolean
declare var __TEST__: boolean
declare var __BROWSER__: boolean
declare var __RUNTIME_COMPILE__: boolean
declare var __COMMIT__: string
declare var __VERSION__: string
复制代码

看过vue3源码的同学一定知道这些是vue中的变量, 上面代码表示__DEV__等变量是全局, 并且标注了他们的类型. 这样无论在项目中的哪个ts文件中使用__DEV__, 变量ts编译器都会知道他是boolean类型.

即便你只写js代码, 也可以安装声明文件, 因为如果你用的是vscode, 那么他会自动分析js代码, 如果存在对应的声明文件, vscode会把声明文件的内容作为代码提示.

1、ts 中使用jQuery

jQuery('.a') // 直接写会报错 cannot find name ‘jQuery’

2、此时我们要给jQuery写声明 全局声明

直接在本文档中或放到jQuery.d.ts中

当然实际的声明文件远不止这么简单,但都是类、函数、变量声明的组合

声明变量使用关键字declare来表示声明其后面的全局变量的类型, 比如:

declare var jQuery: (selector: string) => any
declare var n: number;
// 使用 
n=1

这个namespace代表后面的全局变量是一个对象:

// global.d.ts 
declare namespace MyPlugin { 
    var n:number; 
    var s:string; 
    var f:(s:string)=>number; 
    }
 // 使用
 MyPlugin.s.substr(0,1); 
 MyPlugin.n.toFixed(); 
 MyPlugin.f('文字').toFixed();

3、如果还不识别 添加tsconfig文件

// 告诉ts编译器编译目录下所有文件,找到jquery的声明
{
    "include": ["**/*"]
}

4、DefinitelyTyped 是一个为第三方库写ts声明文件的一个社区

打包后放到 npm @type/XXX

5、react的声明文件react.d.ts

里面是遍历了react源文件(js文件无声明)然后给写的声明文件,声明文件中有源文件所有的函数,类等一一对应,我们写ts的时候用引入的是声明文件中的声明,编译的时候会找到声明对应源文件中的东西

export = React;
export as namespace React;

declare namespace React {
    //
    // React Elements
    // ----------------------------------------------------------------------

    type ElementType<P = any> =
        {
            [K in keyof JSX.IntrinsicElements]: P extends JSX.IntrinsicElements[K] ? K : never
        }[keyof JSX.IntrinsicElements] |
        ComponentType<P>;
    /**
     * @deprecated Please use `ElementType`
     */
    function createElement(
        type: "input",
        props?: InputHTMLAttributes<HTMLInputElement> & ClassAttributes<HTMLInputElement> | null,
        ...children: ReactNode[]): DetailedReactHTMLElement<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
    function createElement<P extends HTMLAttributes<T>, T extends HTMLElement>(
        type: keyof ReactHTML,
        props?: ClassAttributes<T> & P | null,
        ...children: ReactNode[]): DetailedReactHTMLElement<P, T>;
        // Context via RenderProps
    interface ProviderProps<T> {
        value: T;
        children?: ReactNode;
    }

react源码中

function createElement(type, config, children) {
  var propName; // Reserved names are extracted

  var props = {};
  var key = null;
  var ref = null;
  var self = null;
  var source = null;
  ........
  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
}

(6)、让vue3支持this.$axios 模块声明

// main.ts
app.config.globalProperties.$axios = axios;
复制代码

功能上我们实现了"this.axios",但是ts并不能自动推断出我们添加了axios", 但是ts并不能自动推断出我们添加了axios",但是ts并不能自动推断出我们添加了axios字段, 所以添加如下声明文件:

// global.d.ts

// axios的实例类型
import { AxiosInstance } from 'axios'

// 声明要扩充@vue/runtime-core包的声明.
// 这里扩充"ComponentCustomProperties"接口, 因为他是vue3中实例的属性的类型.
declare module '@vue/runtime-core' {
  
  // 给`this.$http`提供类型
  interface ComponentCustomProperties {
    $axios: AxiosInstance;
  }
}

这里扩充"ComponentCustomProperties"接口, 因为他是vue3中实例的属性的类型.