Global: Complemento

UMD

Un módulo UMD es aquel que puede usarse como módulo (a través de una importación) o como global (cuando se ejecuta en un entorno sin un cargador de módulos). Muchas bibliotecas populares, como Moment.js, están escritas de esta manera. Por ejemplo, en Node.js o usando RequireJS, escribirías:

ts
import moment = require("moment");
console.log(moment.format());

mientras que en un entorno de navegador vanilla escribirías:

js
console.log(moment.format());

Identificando una biblioteca UMD

Los módulos UMD verifican la existencia de un entorno de cargador de módulos. Este es un patrón fácil de detectar que se parece a algo así:

js
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(["libName"], factory);
} else if (typeof module === "object" && module.exports) {
module.exports = factory(require("libName"));
} else {
root.returnExports = factory(root.libName);
}
}(this, function (b) {

Si ves pruebas para typeof define, typeof window, o typeof module en el código de una biblioteca, especialmente en la parte superior del archivo, casi siempre es una biblioteca UMD.

La documentación para bibliotecas UMD también mostrará a menudo un ejemplo de “Uso en Node.js” mostrando require, y un ejemplo de “Uso en el navegador” mostrando el uso de una etiqueta <script> para cargar el script.

Ejemplos de bibliotecas UMD

La mayoría de las bibliotecas populares ahora están disponibles como paquetes UMD. Los ejemplos incluyen jQuery, Moment.js, lodash y muchas más.

Plantilla

Hay tres plantillas disponibles para módulos, module.d.ts, module-class.d.ts y module-function.d.ts.

Usa module-function.d.ts si tu módulo puede ser llamado como una función:

js
var x = require("foo");
// Nota: llamando a 'x' como una función
var y = x(42);

Asegúrate de leer la nota al pie “El impacto de ES6 en las Firmas de Llamada de Módulos”

Usa module-class.d.ts si tu módulo puede ser construido usando new:

js
var x = require("bar");
// Nota: usando el operador 'new' en la variable importada
var y = new x("hello");

La misma nota al pie aplica a estos módulos.

Si tu módulo no es llamable o construible, usa el archivo module.d.ts.

Complemento de Módulo o Complemento UMD

Un complemento de módulo cambia la forma de otro módulo (ya sea UMD o módulo). Por ejemplo, en Moment.js, moment-range agrega un nuevo método range al objeto moment.

Para los propósitos de escribir un archivo de declaración, escribirás el mismo código ya sea que el módulo que se está cambiando sea un módulo simple o un módulo UMD.

Plantilla

Usa la plantilla module-plugin.d.ts.

Complemento Global

Un complemento global es código global que cambia la forma de algún global. Al igual que con los módulos modificadores globales, estos aumentan la posibilidad de conflictos en tiempo de ejecución.

Por ejemplo, algunas bibliotecas agregan nuevas funciones a Array.prototype o String.prototype.

Identificando complementos globales

Los complementos globales generalmente son fáciles de identificar a partir de su documentación.

Verás ejemplos que se ven así:

js
var x = "hello, world";
// Crea nuevos métodos en tipos incorporados
console.log(x.startsWithHello());
var y = [1, 2, 3];
// Crea nuevos métodos en tipos incorporados
console.log(y.reverseAndSort());

Plantilla

Usa la plantilla global-plugin.d.ts.

Módulos Modificadores Globales

Un módulo modificador global altera los valores existentes en el ámbito global cuando se importan. Por ejemplo, podría existir una biblioteca que agregue nuevos miembros a String.prototype cuando se importe. Este patrón es algo peligroso debido a la posibilidad de conflictos en tiempo de ejecución, pero aún podemos escribir un archivo de declaración para él.

Identificando módulos modificadores globales

Los módulos modificadores globales generalmente son fáciles de identificar a partir de su documentación. En general, son similares a los complementos globales, pero necesitan una llamada require para activar sus efectos.

Podrías ver documentación como esta:

js
// Llamada 'require' que no usa su valor de retorno
var unused = require("magic-string-time");
/* o */
require("magic-string-time");
var x = "hello, world";
// Crea nuevos métodos en tipos incorporados
console.log(x.startsWithHello());
var y = [1, 2, 3];
// Crea nuevos métodos en tipos incorporados
console.log(y.reverseAndSort());

Plantilla

Usa la plantilla global-modifying-module.d.ts.

Consumiendo Dependencias

Existen varios tipos de dependencias que tu biblioteca podría tener. Esta sección muestra cómo importarlas al archivo de declaración.

Dependencias de Bibliotecas Globales

Si tu biblioteca depende de una biblioteca global, usa una directiva /// <reference types="..." />:

ts
/// <reference types="someLib" />
function getThing(): someLib.thing;

Dependencias de Módulos

Si tu biblioteca depende de un módulo, usa una declaración import:

ts
import * as moment from "moment";
function getThing(): moment;

Dependencias de bibliotecas UMD

Desde una Biblioteca Global

Si tu biblioteca global depende de un módulo UMD, usa una directiva /// <reference types:

ts
/// <reference types="moment" />
function getThing(): moment;

Desde una Biblioteca Módulo o UMD

Si tu biblioteca módulo o UMD depende de una biblioteca UMD, usa una declaración import:

ts
import * as someLib from "someLib";

¡No uses una directiva /// <reference para declarar una dependencia a una biblioteca UMD!

Notas al pie

Previniendo Conflictos de Nombres

Ten en cuenta que es posible definir muchos tipos en el ámbito global al escribir un archivo de declaración global. Desaconsejamos encarecidamente esto, ya que conduce a posibles conflictos de nombres irresolubles cuando muchos archivos de declaración están en un proyecto.

Una regla simple a seguir es declarar tipos solo dentro del espacio de nombres de la variable global que define la biblioteca. Por ejemplo, si la biblioteca define el valor global ‘cats’, deberías escribir:

ts
declare namespace cats {
interface KittySettings {}
}

Pero no

ts
// en el nivel superior
interface CatsKittySettings {}

Esta guía también asegura que la biblioteca pueda ser trasladada a UMD sin romper los usuarios del archivo de declaración.

El impacto de ES6 en los Complementos de Módulos

Algunos complementos agregan o modifican exportaciones de nivel superior en módulos existentes. Si bien esto es legal en CommonJS y otros cargadores, los módulos ES6 se consideran inmutables y este patrón no será posible. Debido a que TypeScript es agnóstico al cargador, no hay aplicación en tiempo de compilación de esta política, pero los desarrolladores que intenten hacer la transición a un cargador de módulos ES6 deben ser conscientes de esto.

El impacto de ES6 en las Firmas de Llamada de Módulos

Muchas bibliotecas populares, como Express, se exponen como una función llamable cuando se importan. Por ejemplo, el uso típico de Express se ve así:

ts
import exp = require("express");
var app = exp();

En los cargadores de módulos ES6, el objeto de nivel superior (aquí importado como exp) solo puede tener propiedades; el objeto del módulo de nivel superior nunca es llamable. La solución más común aquí es definir una exportación default para un objeto llamable/construible; algunos shims de cargador de módulos detectarán automáticamente esta situación y reemplazarán el objeto de nivel superior con la exportación default.

Diseño del archivo de la biblioteca

El diseño de tus archivos de declaración debe reflejar el diseño de la biblioteca.

Una biblioteca puede constar de múltiples módulos, como

myLib
+---- index.js
+---- foo.js
+---- bar
+---- index.js
+---- baz.js

These could be imported as

js
var a = require("myLib");
var b = require("myLib/foo");
var c = require("myLib/bar");
var d = require("myLib/bar/baz");

Your declaration files should thus be

@types/myLib
+---- index.d.ts
+---- foo.d.ts
+---- bar
+---- index.d.ts
+---- baz.d.ts
ts
// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~]
// Project: [~THE PROJECT NAME~]
// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]>
/*~ This template shows how to write a global plugin. */
/*~ Write a declaration for the original type and add new members.
*~ For example, this adds a 'toBinaryString' method with overloads to
*~ the built-in number type.
*/
interface Number {
toBinaryString(opts?: MyLibrary.BinaryFormatOptions): string;
toBinaryString(
callback: MyLibrary.BinaryFormatCallback,
opts?: MyLibrary.BinaryFormatOptions
): string;
}
/*~ If you need to declare several types, place them inside a namespace
*~ to avoid adding too many things to the global namespace.
*/
declare namespace MyLibrary {
type BinaryFormatCallback = (n: number) => string;
interface BinaryFormatOptions {
prefix?: string;
padding: number;
}
}

The TypeScript docs are an open source project. Help us improve these pages by sending a Pull Request

Contributors to this page:
MHMohamed Hegazy  (53)
FKFabián Karaben  (6)
JJohnny  (1)
2+

Last updated: 02 may 2025