如何在不导入库的情况下获得VS Code /打字稿自动完成

时间:2019-05-17 16:47:10

标签: typescript

如果某个模块(例如moment.jsknockoutbig.js)包含在<script>标签中,例如

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js">
</script>

,它们定义了全局属性(例如momentkoBig等),如何访问/声明window(或{{1 }})。

例如

global

如何在不包含整个const x = moment() const t = ko.observable() const b = new Big() 库的情况下设置这些全局变量的环境类型?目的是为VS Code和moment.jstscts-loader使用正确键入的全局引用。

对于babel-typescript,类型在moment处公开,但对于其他库(例如node_modules/moment/moment.d.tsknockout),它们在{{1} }。

感觉这很普遍,但是我还没有看到如何实现此目标的有效参考。


这是tsconfig:

big.js

这里是@types/[module]/index.d.ts

{
    "compilerOptions": {
      "target": "ESNext",
      "moduleResolution": "node",
      "allowJs": true,
      "noEmit": true,
      "strict": false,
      "isolatedModules": false,
      "esModuleInterop": true,
      "noResolve": false,
      "baseUrl": ".",
      "paths": {
        "*": [
          "*",
          "js.packages/*"
        ]
      },
      "jsx": "preserve",
      "outDir": "dist/"
  },
  "include": [
    "js.packages/**/*.ts",
    "js.packages/**/*.tsx",
    "js.packages/@types/lib.d.ts",
  ],
  "files": [
    "services/app/src/entry.js"
  ],
  "exclude": [
    "node_modules"
  ]
}

这是消费的工作方式:

lib.d.ts

在VS代码中看起来像这样(红色下划线表示失败):

failing types

因为declare global { type Bigable = Big | string | number interface Window { Big: typeof import('big.js'), moment: typeof import('moment'), Sentry: typeof import('@sentry/browser'), } } 具有:

const v = new Big(1)
const m = moment()
const s = global.Sentry()
const o = ko.observable()

与此类似,我在@types/knockout/index.d.ts上声明了全局declare var ko: KnockoutStatic; declare module "knockout" { export = ko; }

不幸的是,Biginterface Window(在此示例中)似乎不起作用,并且尚不清楚为什么或可能需要做些什么来解决此问题。

2 个答案:

答案 0 :(得分:2)

您的想法正确,您需要使用import类型来获取导入中的类型,您需要在global中声明变量。问题是您要声明Window上的属性。尽管分配给Window的任何键都变成了全局变量打字稿,但并不能反映这一点。您可以直接在全局范围内声明变量。

declare global {
  export var moment: typeof import('moment');
  export var Sentry: typeof import('@sentry/browser');
}

const m = moment()
Sentry.init({}) // Sentry() does not seem like it should work according to docs

答案 1 :(得分:0)

这个问题并非特别针对一种平台,但我将告诉您如何在Angular中使用moment

首先,您不应该从脚本URL进行加载。您应该运行npm install moment将其放入您的node_modules文件夹中。这将确保将其打包到应用程序的缩小版本中。您不必这样做,但强烈建议这样做。

"scripts": [
          "node_modules/jquery/dist/jquery.slim.min.js",
          "node_modules/moment/moment.js",
           ...
        ]

无论采用哪种方法,一旦在tsconfig(或angular.json)中链接了脚本,用法就如同文件顶部的以下行一样简单:

import * as moment from 'moment';

我倾向于将这种语法用于大多数具有对象的库,例如shortidlinqlodash

其他库与declare var语句配合使用效果更好。例如,我发现jQuery可以更好地工作。

declare var $

自动完成

如果要查找自动完成功能,则需要为该库加载一个.d.ts文件。 moment的npm软件包随附一个,但是某些库需要为此安装另一个npm软件包(例如@types/lodash@types/jquery)。

Visual Studio自动完成功能依靠.d.ts文件来识别类型。 here中提供了有关配置此功能的文档,可以对其进行配置(请参阅底部附近的注释)。