npm - Globala Typescript-deklarationer syns inte utanför node_modules/@types


Kontext

Jag utvecklar ett npm-paket med Typescript så typer skickas med tillsammans med biblioteket, i princip:

my-package
|- index.js
|- index.d.ts
|- package.json

index.d.ts-filen innehåller globala element, något i stil med:

declare var thisIsAGlobal: string

Problemet

Efter att ha publicerat paketet och installerat det i ett annat projekt med npm i my-package syns inte globala variabler i Typescript, om du inte uttryckligen import 'my-package' eller /// <reference types="my-package" /> i någon fil i projektet, efter det blir de globala variablerna synliga.

Projekt :

- node_modules
 |- my-library
   |- index.d.ts
- src
 |- index.ts  // thisIsAGlobal global not visible
 |- other_file.ts // thisIsAGlobal global not visible

Upptäckter

När jag försökte reversera Jest-typer, som mestadels exporterar globala objekt, upptäckte jag att den enda skillnaden mellan mina globala objekt och Jest-globala objekt är platsen; Jest-globala objekt finns i node_modules/@types/jest/index.d.ts medan mina finns utanför node_modules/@types. I början trodde jag att det hade att göra med package.json eller någon typkonfiguration, men jag gjorde följande experiment:

Jag skapade manuellt en enskild fil (med en global i) inne i en mapp i node_modules/@types och den globala var synlig inom mina projektfiler.

- node_modules
 |- @types
   |- experiment
     |- index.d.ts  // declare var thisIsAGlobal: number

Om jag tar experimentfilen utanför @types-katalogen slutar globalen att vara synlig inom projektfilerna.

- node_modules
 |- @types
 |- experiment
   |- index.d.ts  // declare var thisIsAGlobal: number

Du behöver inte ens en package.json-fil i @types-katalogen för att TypeScript ska kunna hämta globala typer.

Fråga

Är det något jag missar när jag publicerar ett paket med globala typer?

Kanske för typer utanför @types behöver du en speciell konfiguration?

Svar #1

Som standard skannas node_modules/@types alltid:

Som standard inkluderas alla synliga ”@types”-paket i din kompilering. Paket i node_modules/@types i någon omgivande mapp anses vara synliga. -- https://www.typescriptlang.org/tsconfig#types

Du kan se @types tas in utan villkor (givet standard tsconfig.json) med tsc --traceResolution.

Det visar sig, som du har upptäckt, att node_modules-paket bara skannas om du faktiskt importerar något från det givna paketet. Jag kan inte hitta någon motivering eller diskussion för att alla node_modules-paket inte skannas som standard, men det verkar ganska rimligt att inte bara skanna varje paket i node_modules för typer som standard. Det är potentiellt en stor mängd skanning. Dessutom kommer eventuella typer (globala eller andra) från dessa paket bara att vara relevanta om du faktiskt importerar något från dem (paketet kan inte ändra globalt tillstånd om det aldrig importeras). Tvärtom verkar det rimligt att skanna @types som standard så att några globala typer för saker som node (@types/node) som du implicit använder men inte importerar kan samlas in. Ett sista argument är att importering av alla typer från node_modules som standard kommer att öka sannolikheten för krockar.

Dokumentationen säger att om du vill importera globala deklarationer från ett "globalt bibliotek" och inte importerar något från det bör du använda:

/// <reference types="someLib" />

Relaterade artiklar