01.申明全局变量

214 阅读2分钟

在 TypeScript(isolatedModules: true)中,就像在 ECMAScript 2015 中一样,任何包含顶级importoutput的文件都被视为模块

相反,没有任何顶级importoutput声明的文件被视为其内容在全局范围内可用的脚本(因此可直接在模块中使用)。

1.申明全局类型/变量/函数

1.1: 在包含import/export的.ts/.d.ts文件中,使用global从模块内部将声明添加到全局范围

import type { App } from "vue";
declare global {
    // 全局类型
    interface myInterFace {
        app: App
    }

    // 全局变量
    const $: any

    // 全局函数
    const createApp: typeof import('vue')['createApp']

    // 对已有申明进行扩充 ??
    interface Array<T> {
      toObservable: () => {};
    }

    // 不能申明模块
    // module xxxx
}

  - 申明的全局函数createApp可使在main.ts不必import { createApp } from 'vue'即可直接const app = createApp(App),这也是插件unplugin-vue-components中使用的方法

1.2: 在不包含import/export的.d.ts文件中,直接申明

// 全局类型
declare interface myInterFace {
}

// 全局变量
declare const $: any

// 全局函数
declare const myFun: (str: string) => string

// 对已有申明进行扩充 ?? 不用declare ??
interface Array<T> {
  toObservable: () => {};
}

// 申明模块 // import{ a }form 'loadsh' loadsh.a
declare module '*loadsh' {
  let a: stirng
}

  - 注意:如果在.ts文件中这样定义时,因为开启了(isolatedModules: true),所以会导致报错(需要顶级的import/output),倘如加入export {} 会使这些申明变成了模块内的局部申明,并非全局申明。

2. 对某一模块内的已有申明的扩充

2.1 在.ts/.d.ts文件中通过导入的方式(就已是一個模块)对已有类型进行扩充声明

// observable.ts
export interface Observable{
}

// map.ts
declare module "./observable" {  // 对该模块(文件)内的已有申明进行扩充
  interface Observable {
    map: () => {};
  }
}


// consumer.ts
import { Observable } from "./observable";
// import "./map"; //?
let o: Observable;
o.map();

// dependencies vue
export interface ComponentCustomProperties{ 
}

// xx.ts
import axios from 'axios'

declare module 'vue' { // 对该模块(文件)内的已有申明进行扩充
  // 用于增强组件实例类型以支持自定义全局属性。
  interface ComponentCustomProperties {
    $http: typeof axios
  }
}

// App.vue
getCurrentInstance()?.proxy?.$http()

3. Vue的解释

类型扩展的位置:

我们可以将这些类型扩展放在一个 .ts 文件,或是一个影响整个项目的 *.d.ts 文件中。无论哪一种,都应确保在 tsconfig.json 中包括了此文件。

对于库或插件作者,这个文件应该在 package.json 的 types 属性中被列出。

为了利用模块扩展的优势,你需要确保将扩展的模块放在 TypeScript模块中。 

也就是说,该文件需要包含至少一个顶级的 importexport,即使它只是 export {}。

如果扩展被放在模块之外,它将覆盖原始类型,而不是扩展!

  模块名称的解析方式与导入/导出中的模块说明符相同。然后,扩充中的声明将合并,就像它们在与原始声明相同的文件中一样。

  但是,需要记住两个限制:

  - 您不能在扩充中声明新的顶级声明,只能对现有声明进行修补

  - 默认导出也不能扩充只能扩充命名导出(因为您需要通过导出的名称扩充导出,并且默认是保留字)