详细介绍TypeScript中的“declare”关键字的作用,这样你对*.d.ts文件就不陌生了。
当你在TypeScript项目中打开?*.d.ts
?声明文件时,你可能会看到?declare
?。你知道?declare
?是做什么的吗?如果你不知道,读完这篇文章,也许你就会知道了。
在TypeScript项目中,你可以以脚本标签的形式导入第三方JS-SDK,比如导入Google Maps平台的JS-SDK。
<script?src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"?defer></script>
初始化之后,你将在TypeScript文件中调用JS-SDK公开的API。
尽管根据Google Maps开发文档,你正在使用JS-SDK提供的API, TypeScript编译器仍然会为上述代码提示相应的错误消息。这是因为TypeScript编译器不能识别全局变量?google
?。
那么如何解决这个问题呢?答案是使用?declare
?关键字来声明?google
?全局变量,以便TypeScript编译器能够识别该全局变量。
declare var google: any;
看到这里,你会感到困惑吗? 为什么你可以在TypeScript项目中使用全局变量,比如?JSON
?、?Math
?或?Object
?? 这是因为TypeScript在内部为我们做了声明,而前面提到的全局变量是在lib.es5.d.ts声明文件中声明的。??????
// typescript/lib/lib.es5.d.ts
declare var JSON: JSON;
declare var Math: Math;
declare var Object: ObjectConstructor;
事实上,除了声明全局变量之外,declare关键字还可以用于声明全局函数、全局类或全局枚举类型。像?eval
?、?isNaN
?、?encodeURI
?和?parseInt
? 这些你可能在工作中使用过的函数也在lib.es5.d.ts声明文件中声明:
declare function eval(x: string): any;
declare function isNaN(number: number): boolean;
declare function encodeURI(uri: string): string;
declare function parseInt(string: string, radix?: number): number;
应该注意的是,当声明一个全局函数时,我们不包括函数的具体实现。有了声明文件,TypeScript编译器就能识别出上面的全局JavaScript函数。
之前解决找不到“google”这个名字的问题的方法是比较暴力的。一个更好的解决方案是使用TypeScript网站或DefinitelyTyped项目上提供的类型声明文件搜索功能,这样你就可以找到更高质量的第三方库类型声明文件。
DefinitelyTyped项目是一个开源项目,它维护许多包的类型声明文件。
找到之后,你就可以通过npm安装带有所需类型声明文件的模块。如果你读过关于使用TypeScript和谷歌地图的指南。您可以找到与Google Maps相对应的类型声明文件。之后,你可以使用npm来安装它:
npm i -D @types/google.maps
对于npm包"foo",它的类型是"@types/foo"。例如,更熟悉的jquery库具有包名??
@types/jquery
接下来,我们将介绍“declare”的其他用法。当您在Vite项目中打开?client.d.ts
?声明文件时,您将看到大量声明模块的代码。
在上面的代码中,我们声明了?css
?、?jpg
?和?ttf
?模块。为什么需要声明这些模块? 因为如果你不声明它们,TypeScript编译器将无法识别这些模块,并会提示相应的错误消息。
在声明模块时,为了避免每个资源都用它对应的模块来声明,TypeScript 2.0开始支持通配符(*)形式来声明模块名。
此外,TypeScript允许你通过declare module语法扩展现有模块中定义的类型。例如,如果你想为每个Vue组件实例添加?$axios
?属性,你可以这样做:
import { AxiosInstance } from "axios";
declare module "@vue/runtime-core" {
interface ComponentCustomProperties {
$axios: AxiosInstance;
}
}
然后,使用config对象的?globalProperties
? 属性,你可以有效地为每个组件实例添加?$axios
? 属性:
import { createApp } from "vue";
import axios from "axios";
import App from "./App.vue";
??????
const app = createApp(App);
app.config.globalProperties.$axios = axios;
app.mount("#app");
最后,在组件中,你可以通过组件内部实例的?proxy.$axios
?属性访问axios对象:
import { getCurrentInstance , ComponentInternalInstance} from "vue"
const { proxy } = getCurrentInstance() as ComponentInternalInstance
proxy!.$axios
.get("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => response.data)
.then((json) => console.log(json));
读完本文,相信您已经了解了?declare
?关键字的作用和一些常见的应用场景。
欢迎关注公众号:文本魔术,了解更多
?