TypeScript -声明文件

遇到问题:

开发超五card过程中,使用TypeScript写代码,因为项目中需要引入moment,来处理日期格式问题。像往常一样下载引入:

tnpm i moment --save
import * as moment from 'moment';

引入后发现有红色波浪线,但是页面并没有报错

image.png

 

前端第三方库大多都是非 TypeScript 库,基本上都是使用 JS 编写的,在 TS 中使用非 TS 编写的第三方库,需要有个 xx.d.ts 声明文件。引入声明文件后,就能获得对应的代码补全、接口提示等功能。这里的报错就是缺少声明文件引起的。

 

解决方案:

 

一,npm包

首先,查找下社区有没有引入模块的声明文件。通过 https://www.npmjs.com/ 网址进行搜索。一般依赖的格式为 @types/xxxx 。例如:@types/jQuery,@types/lodash等等。如果可以搜索到,就直接安装。npm install @types/lodash --save-dev。一般情况下会自动查找node?_modules/@types中的声明文件。

二,某些模块自带声明文件

有些模自带声明文件。判断依据是 package.json 中有 types 字段,或者有一个 index.d.ts 声明文件。这种模式不需要额外安装其他包,是最为推荐的,所以以后我们自己创建 npm 包的时候,最好也将声明文件与 npm 包绑定在一起。

 

例如:和 moment 等等。node_modules中找到moment模块,打开可以看到自带了声明文件,但是还是会有报错的问题。这里可能是momet的声明文件有点问题。

image.png

对于moment的声明文件,我的解决方法是这样的:

npm i typings  项目中会多个typings文件夹
typings install dt~moment --global --save

image.png

刚刚下载的moment的声明文件被放在typings下面

index.d.ts文件内容:

 

这是一种引入.d.ts文件的方式。

修改tsconfig.json配置文件,include属性中新增一个typings元素,这样如果node_modules中找不到声明文件,就会去typings中查找。

{
  "compilerOptions": {
    "baseUrl": ".",
    "target": "es6",
    "noImplicitThis": true,
    "noImplicitUseStrict": true,
    "types": ["mini-types"]
  },
  "include": [
    "src/**/*",
    "typings", // 新增
  ]
}

这样报错就没有了,鼠标放在引入的moment上面,可以很清楚的看到提示信息:

image.png

三,自己写声明文件

如果以上两种方式都不能解决问题,就需要自己写声明文件了。

比如在项目中引入一个第三方工具库:

import startApp from '@alipay/merchant-mini-utils/startApp';

这个工具没有自己的声明文件。

可以在typings/index.d.ts文件中写自己的声明语句,扩展全局模块:

declare module "@alipay/merchant-mini-utils/startApp" {
  type Params = {
    appId: string;
    startMultApp: string;
    redirect: boolean;
    success: () => void;
    fail: () => void
  };
  export default function startApp(url: string, params?: Params): void
}

在文件引入的地方可以看到提示信息,一眼就知道函数的使用方法,需要传递什么参数。

image.png

这里留有一个问题,感觉这样写不太对,未完待续。。。。

声明文件的书写规范

声明文件的新语法有:

一 声明全局变量

  • 文件内容定义了一个变量:
var a = 10;

引入方式:

<script src="./index.js"></script>

引入之后,变量a便可以全局使用,这个时候就需要在inde.d.ts文件中声明一个全局变量:

declare var a:number;

 

这样就可以在ts文件直接使用这个全局变量了。

二 声明全局函数和带有子属性的全局对象

  • 文件内容定义了一个函数,函数也是对象,带有自己的静态属性:
function globalFunc(params){
    console.log(params);
};
globalFunc.version = "v1.0.0";
globalFunc.dosomething = function(){
    console.log("I am globalFunc  dosomething");
};
<script src="./globalFunc.js"></script>

声明文件:

declare function globalFunc(params:globalFunc.params):void
//类型兼容性
declare namespace globalFunc{
    const version : string;
    interface params{
        [key:string]:any
    }
    function dosomething():void;
}

注意,在声明文件中声明的类型,接口都会是全局的,尽量放在局部环境中去声明。

declare function 声明全局函数

declare namespace 声明(含有子属性的)全局对象

三 扩展全局变量

上面函数文件引入html后,会成为一个全局的函数。如果我在index.ts文件中想要对这个全局函数进行扩展:

globalFunc.add = ()=>{};
//报错如下
//Property 'add' does not exist on type 'typeof globalFunc'.

就需要增加声明:

declare global {
    namespace globalFunc{
        function add() :void
    }
}
globalFunc.add = ()=>{};
Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.
全局作用域的扩展只能直接嵌套在外部模块或环境模块声明中

可以理解为 declare global 直接作用在模块中,也就是必须出现 import 或者 export 这些文件里面,这个文件才不会被当成一个全局的 TS 脚本,而是模块。所以,我们可以导出一个空对象,用来告诉编译器这是一个模块的声明文件。

// declare global 扩展全局变量
export {}
declare global {
    namespace globalFunc{
        function add() :void
    }
}
globalFunc.add = ()=>{};
console.log(globalFunc.add());

通过 declare global 可以扩展全局变量。

四:扩展全局模块

项目中引入了moment模块,通过这种方式引入:import moment from "moment"

如果想对moment对象扩展一个方法:

moment.getDate = function(){
    const date = new Date();
    return Number(date);
};

就需要增加声明文件:

declare module "moment" {
    export function getDate():number;
}

通过 declare module 可以直接扩展第三方模块。

比如在taro创建的小程序中使用typescript开发,引入第三方组件库:

import { View, Button, Text } from '@tarojs/components';

需要为这个第三方组件库写声明文件:

global.d.ts 

declare module '@tarojs/components' {
  export const View: React.ComponentType<any>;
  export const Button: React.ComponentType<any>;
  export const Text: React.ComponentType<any>;

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值