【问题标题】:How to typecheck a .js file that uses Moment using TypeScript?如何使用 TypeScript 对使用 Moment 的 .js 文件进行类型检查?
【发布时间】:2019-07-30 03:29:28
【问题描述】:

我有一个使用 Moment 的小 .js 文件,旨在直接在浏览器中运行,我想使用 TypeScript 编译器进行类型检查:

document.querySelector("body").textContent = moment().toString();

如果我尝试使用tsc 对其进行类型检查,编译器会抱怨它找不到moment 的声明,即使我安装了moment npm 包:

$ npm install typescript moment
$ node_modules/.bin/tsc --allowJs --checkJs --noEmit index.js
index.js:1:46 - error TS2304: Cannot find name 'moment'.

1 document.querySelector("body").textContent = moment().toString();
                                               ~~~~~~
Found 1 error.

如何让 TypeScript 编译器自动检测 moment 全局对象或在 JS 文件中显式导入它?

【问题讨论】:

    标签: typescript momentjs


    【解决方案1】:

    暂时

    使用内容创建一个文件moment.shims.d.ts

    import moment from '../../node_modules/moment/moment';
    
    export = moment;
    
    export as namespace moment;
    

    (更改导入行以指向您在 node_modules 中安装的 moment 版本。)

    将此 shims 文件与您的 TypeScript 项目的其余部分一起编译。

    您可能需要在您的tsconfig.json 或您对tsc --esModuleInterop true 的呼叫中启用esModuleInterop 选项:

    {
        ...
        "compilerOptions": {
            ...
            "esModuleInterop": true,  // needed by: moment.shims.d.ts
        },
    }
    

    暂时 > 2.24.0

    一旦this PR 被接受,无需特殊操作。

    【讨论】:

    • 这很好用!不过,它可以使用一个小的调整:与其在 2.24 shim 中引用 moment.d.ts 的完整路径,您可以在第一行中简单地... import moment from "moment"
    【解决方案2】:

    如果它在全球范围内可用,您可以使用:

    declare var moment:any

    这告诉 typescript 时刻在别处声明,它不应该抛出错误。

    如果你想要更强类型的代码,你也可以指定类型而不是any

    【讨论】:

    • 这将允许您检查像 moment() 这样的表达式,但不能检查像 /** @type moment.Moment */ 这样的类型注释
    【解决方案3】:

    你是如何导入moment 包的?

    我在这里使用 require / CommonJS 语法没有收到任何错误:

    // index.js
    
    const moment = require("moment")
    
    document.querySelector("body").textContent = moment().toString();
    

    tsc --allowJs --checkJs --noEmit src/index.js 测试没有错误。

    现在如果你想使用 ES6 语法,你可以这样做:

    // index.js
    
    import moment from 'moment'
    
    document.querySelector("body").textContent = moment().toString();
    

    并在您的 tsconfig.json 文件中的 compilerOptions 下添加 "esModuleInterop": true

    【讨论】:

    • 我正在使用 .js 文件中的时刻,旨在直接在浏览器中运行,因此没有导入。
    • 您使用的是 Parcel 或 Webpack 之类的打包工具吗?因为这些会将moment 捆绑在您的Web 应用程序中,即使将moment 用作库,您也可以直接在浏览器中运行它。
    • 这里没有 Webpack 或 Parcel。对于我们的生产版本,有连接和缩小,但没有捆绑(进口或要求)。开发构建直接运行,根本没有任何转换。
    猜你喜欢
    • 2019-01-19
    • 1970-01-01
    • 1970-01-01
    • 2017-09-09
    • 1970-01-01
    • 2019-08-22
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    相关资源
    最近更新 更多