microsoft / microsoft/TypeScript

Nested application of "typesVersions" mappings

Offen
#43,078 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Awaiting More Feedback Suggestion
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.3k
Ø Merge
2 T. 4 Std.
Gemergte PRs (30 T.)
132

Beschreibung

Suggestion / Bug Report

This is a combination bug/FR. I'm not sure if some other TypeScript setting can solve this problem.

🔍 Search Terms

  • typesVersions

✅ Viability Checklist

My suggestion meets these guidelines:

  • [?] This wouldn't be a breaking change in existing TypeScript/JavaScript code
    • (I'm not sure, though I think the risk is low.)
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion/Bug

It seems like typesVersions in package.json can only influence the root declarations that are loaded for a package. It would be helpful if it could also map paths deeper within the type module graph. The TypeScript 3.1 Release Notes introducing typesVersions say that "if you’re familiar with path mapping today, it works exactly like that." However, tsconfig.json paths can remap import paths anywhere within the project's own module hierarchy. This is why I say it's also a bug, because in my mind the documentation suggests that typesVersions is capable of something it isn't.

The Publishing page on the TypeScript docs doesn't include that language, but it's also not the first thing that comes up when you search for "typescript typesVersions".

I've put together a quick repro repository on my GitHub account that illustrates this.

📃 Motivating Example

Currently, if your package provides type declarations that export a set of declarations from a nested module, it is troublesome for library authors to provide differing type definitions of nested-module for users of older TypeScript versions without providing completely separate root declaration files:

// /my-root-package.d.ts

export declare function doSomething(): void;

// If this file is the root of my declarations, then there's no way to remap just the
// contents of the following import for older TS versions
export * from "./nested-module/latest/index.d.ts";`

With nested application of typesVersions, an entry in the package.json typesVersions field can apply to this import in the declarations and remap it when the compiler loads the types:

{
  // ...
  "typesVersions": {
    "<3.6": {
      "nested-module/latest/*": ["nested-module/3.1/*"]
    }
  }
}

This nested application of typesVersions mappings will be used when the declaration file for a package is a module (contains import or export statements).

💻 Use Cases

In the Azure SDK for JavaScript, we're building isomorphic libraries, and we don't want to assume that consumers of our APIs have DOM types loaded in their project, so we use DOM types in our compilation, but only provide empty shims for the DOM types that appear in our public API surface (we may have a method that optionally consumes RequestInit for example). We also use the following stack to manage our type declarations:

  • api-extractor (for d.ts-rollup, allowing us to ship declarations of only our public API surface area)
  • downlevel-dts (to allow us to support older versions of typescript without support for things like getters/setters)

We emit our rolled-up types into types/latest/<package>.d.ts for newer versions of TS and types/3.1/<package>.d.ts for TS older than 3.6. The best way we've found to tie all of this together with our shims is to create a hand-written declaration module that declares the interface shims we need into the global scope, and then re-exports our actual API types, like the following:

// /core-rest-pipeline.shims.d.ts

declare global {
  // These shims can be overridden if a consumer loads lib.dom.d.ts
  interface FormData {}
  interface RequestInit {}
  // etc.
}

export * from "./types/latest/core-rest-pipeline.d.ts";

This allows Node consumers to use our libraries without lib.dom.d.ts. However, because typesVersions can only influence the selection of the root type declaration file, we have to provide this shim twice and use typesVersions to remap the shim file. It's a small nuisance, but a nuisance nonetheless that we can't just remap the import within a single shim file.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne mit dem verlinkten Repository typesversions-repro sowie dessen package.json und Deklarationsdateien, um nachzuvollziehen, wie typesVersions die Root-Deklaration und verschachtelte Exporte behandelt. Vergleiche dieses Verhalten mit den Pfaden in tsconfig.json sowie mit der TypeScript-Dokumentation zu Releases und zum Publizieren. Als erledigt gilt die Aufgabe, wenn verschachtelte Deklarationsimporte für ältere TypeScript-Versionen umgeleitet werden können, ohne den Root-Shim oder die Deklarationsdatei zu duplizieren.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
typescript
Bereich
compilers
Issue-Typ
Feature
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
30/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.