简体   繁体   中英

How to get VS Code / typescript autocomplete without importing the library

If a module (eg moment.js , knockout , or big.js ) is included with a <script> tag eg

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

that define a global property (eg moment , ko , Big , etc), how can one access/declare the types on window (or global ) in Typescript.

For example

const x = moment()
const t = ko.observable()
const b = new Big()

How can one set the ambient type of these globals without including the entire moment.js library? The objective is to have properly typed global references to be used by VS Code, and tsc , ts-loader , or babel-typescript .

In the case of moment , the types are exposed at node_modules/moment/moment.d.ts , but for other libraries (eg knockout or big.js ) they're at @types/[module]/index.d.ts .

It feels like this would be quite common, but I haven't seen a good, working reference of how to accomplish this.


Here is the tsconfig:

{
    "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"
  ]
}

Here's a lib.d.ts

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

and here's how consumption should work:

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

which looks like this in VS Code (with the red underline indicating failures):

失败的类型

So knockout works because @types/knockout/index.d.ts has:

declare var ko: KnockoutStatic;
declare module "knockout" {
    export = ko;
}

whereas I've similarly declared a global Big on interface Window .

Unfortunately Sentry and moment (in this example) do not seem to work, and it's unclear why or what one might have to do to fix this.

You have the right idea, you need to use an import type to get the types in an import, you need to declare variables in global . The problem is that you are declaring the properties on Window . While any key assigned to Window becomes a global variable typescript does not reflect this. You can declare the variables directly in the global scope.

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

The question is not terribly specific to one type of platform, but I'll tell you how I get moment working in Angular.

First, you shouldn't be loading from a script URL. You should run npm install moment to put it in your node_modules folder. This will ensure it gets packed up into the minified version of your application. You don't have to, but this is strongly recommended.

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

Regardless of the above, once you have the script linked in your tsconfig (or angular.json ), usage is as simple as the following line at the top of the file:

import * as moment from 'moment';

I tend to use this syntax for most libraries which have an object, eg shortid , linq , and lodash .

Other libraries work better with declare var statements. For example, I've found jQuery to work better that way.

declare var $

Autocomplete

If you're looking for autocomplete, you need to have a .d.ts file loaded for the library. The npm package for moment comes with one, but some libraries need to have another npm package installed for this (eg @types/lodash , @types/jquery ).

Visual Studio Autocomplete relies upon .d.ts files to identify types. The documentation for configuring this feature is located here , and it may be possible to configure it (see the note near the bottom).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM