Cómo obtener la autocompletación de VS Code/TypeScript sin importar la biblioteca
Si un módulo (por ejemplo, moment.js, knockout o big.js) se incluye con una etiqueta <script>, por ejemplo
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js">
</script>
que definen una propiedad global (por ejemplo, moment, ko, Big, etc.), ¿cómo puede uno acceder/declarar los tipos en window (o global) en TypeScript?
Por ejemplo
const x = moment()
const t = ko.observable()
const b = new Big()
¿Cómo puede uno establecer el tipo ambiental de estos globales sin incluir toda la biblioteca moment.js? El objetivo es tener referencias globales correctamente tipadas para ser utilizadas por VS Code, y tsc, ts-loader o babel-typescript.
En el caso de moment, los tipos se exponen en node_modules/moment/moment.d.ts, pero para otras bibliotecas (por ejemplo, knockout o big.js) están en @types/[module]/index.d.ts.
Parece que esto sería bastante común, pero no he visto una referencia buena y funcional de cómo lograrlo.
Aquí está el 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"
]
}
Aquí está un 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'),
}
}
y así es como debería funcionar el consumo:
const v = new Big(1)
const m = moment()
const s = global.Sentry()
const o = ko.observable()
que se ve así en VS Code (con la subrayado rojo indicando fallos):
Entonces knockout funciona porque @types/knockout/index.d.ts tiene:
declare var ko: KnockoutStatic;
declare module "knockout" {
export = ko;
}
mientras que yo he declarado de manera similar un Big global en interface Window.
Desafortunadamente, Sentry y moment (en este ejemplo) no parecen funcionar, y no está claro por qué o qué se podría hacer para solucionar esto.
Respuesta #1
Tienes la idea correcta, necesitas usar un tipo import para obtener los tipos en una importación, necesitas declarar las variables en global. El problema es que estás declarando las propiedades en Window. Aunque cualquier clave asignada a Window se convierte en una variable global, TypeScript no refleja esto. Puedes declarar las variables directamente en el ámbito global.
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
Respuesta #2
La pregunta no es terriblemente específica para un tipo de plataforma, pero te contaré cómo hago que moment funcione en Angular.
Primero, no deberías estar cargando desde una URL de script. Deberías ejecutar npm install moment para ponerlo en tu carpeta node_modules. Esto asegurará que se incluya en la versión minimizada de tu aplicación. No es obligatorio, pero se recomienda encarecidamente.
"scripts": [
"node_modules/jquery/dist/jquery.slim.min.js",
"node_modules/moment/moment.js",
...
]
Independientemente de lo anterior, una vez que tenga el script vinculado en su tsconfig (o angular.json), el uso es tan simple como la siguiente línea al principio del archivo:
import * as moment from 'moment';Suelo usar esta sintaxis para la mayoría de las bibliotecas que tienen un objeto, por ejemplo shortid, linq y lodash.
Otras bibliotecas funcionan mejor con las declaraciones declare var. Por ejemplo, he encontrado que jQuery funciona mejor de esa manera.
declare var $Autocompletar
Si estás buscando autocompletado, necesitas tener un archivo .d.ts cargado para la biblioteca. El paquete de npm para moment viene con uno, pero algunas bibliotecas necesitan que se instale otro paquete de npm para esto (por ejemplo, @types/lodash, @types/jquery).
La función de Autocompletar de Visual Studio se basa en archivos .d.ts para identificar tipos. La documentación para configurar esta función se encuentra aquí, y puede ser posible configurarla (ver la nota cerca del final).
