Hvordan få VS Code/TypeScript fullføring uten å importere biblioteket
Hvis en modul (f.eks. moment.js, knockout eller big.js) inkluderes med en <script>-tagg f.eks.
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js">
</script>
som definerer en global egenskap (f.eks. moment, ko, Big, osv.), hvordan kan man få tilgang til/erklære typene på window (eller global) i Typescript.
For eksempel
const x = moment()
const t = ko.observable()
const b = new Big()
Hvordan kan man sette den ambient-typen til disse globale uten å inkludere hele moment.js-biblioteket? Målet er å ha korrekt typede globale referanser som kan brukes av VS Code, og tsc, ts-loader eller babel-typescript.
I tilfellet med moment er typene eksponert på node_modules/moment/moment.d.ts, men for andre biblioteker (f.eks. knockout eller big.js) er de på @types/[module]/index.d.ts.
Det føles som om dette ville vært ganske vanlig, men jeg har ikke sett en god, fungerende referanse på hvordan man kan oppnå dette.
Her er 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"
]
}
Her er en 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'),
}
}
og her er hvordan forbruk bør fungere:
const v = new Big(1)
const m = moment()
const s = global.Sentry()
const o = ko.observable()
som ser slik ut i VS Code (med den røde understrekingen som indikerer feil):
Så knockout fungerer fordi @types/knockout/index.d.ts har:
declare var ko: KnockoutStatic;
declare module "knockout" {
export = ko;
}
mens jeg på samme måte har erklært en global Big på interface Window.
Dessverre ser det ut til at Sentry og moment (i dette eksemplet) ikke fungerer, og det er uklart hvorfor eller hva man måtte gjøre for å fikse dette.
Svar #1
Du har den riktige ideen, du må bruke en import-type for å få typene i en import, du må erklære variabler i global. Problemet er at du erklærer egenskapene på Window. Selv om enhver nøkkel som tildeles Window blir en global variabel, reflekterer ikke TypeScript dette. Du kan erklære variablene direkte i det globale området.
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
Svar #2
Spørsmålet er ikke spesielt spesifikt for én type plattform, men jeg skal fortelle deg hvordan jeg får moment til å fungere i Angular.
Først bør du ikke laste fra en skript-URL. Du bør kjøre npm install moment for å plassere det i mappen node_modules. Dette vil sikre at det blir pakket inn i den minifiserte versjonen av applikasjonen din. Du trenger ikke, men dette anbefales sterkt.
"scripts": [
"node_modules/jquery/dist/jquery.slim.min.js",
"node_modules/moment/moment.js",
...
]
Uavhengig av det ovennevnte, når du har skriptet koblet i din tsconfig (eller angular.json), er bruken så enkel som følgende linje øverst i filen:
import * as moment from 'moment';Jeg pleier å bruke denne syntaksen for de fleste biblioteker som har et objekt, for eksempel shortid, linq, og lodash.
Andre biblioteker fungerer bedre med declare var-erklæringer. For eksempel har jeg funnet at jQuery fungerer bedre på den måten.
declare var $Autofullfør
Hvis du leter etter autoutfylling, må du ha en .d.ts-fil lastet for biblioteket. npm-pakken for moment kommer med en, men noen biblioteker må ha en annen npm-pakke installert for dette (f.eks. @types/lodash, @types/jquery).
Visual Studio Autocomplete er avhengig av .d.ts-filer for å identifisere typer. Dokumentasjonen for å konfigurere denne funksjonen finnes her, og det kan være mulig å konfigurere den (se merknaden nær bunnen).
