microsoft / microsoft/TypeScript

Generic parameter type checking stops too early

Offen
#59,049 10 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

In Discussion Suggestion
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.4k
Ø Merge
1 T. 19 Std.
Gemergte PRs (30 T.)
117

Beschreibung

🔎 Search Terms

generic, early, permature, defer

🕗 Version & Regression Information
  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about _________
⏯ Playground Link

https://www.typescriptlang.org/play/?ssl=10&ssc=1&pln=1&pc=1#code/JYOwLgpgTgZghgYwgAgEoRgeQEYCsIJgA8AKgHzIDeAUMncggK5RQTgBcyJyAPsiIwA2g6gF9q1ACYFBcVshiMQhYAHsQySAGcwACgAendFjwFiAgLbZoZAJScAbquCSA3FJlyUi5WDUaAcwgwY117NAwcfEIiS2soXn4hQTJ3akFg5AdkAF5kIJCMMPdtPQdbdyA

💻 Code
interface RefObject<T> {
    current: T | null
}

declare function test(x: RefObject<number>): void;
declare function getRef(): RefObject<number | null>;

let v = getRef();
test(v);
🙁 Actual behavior

In the above code, RefObject is defined to always accept null in its current property. However, if one explicitly writes RefObject<number | null> and passes the result to a parameter accepting RefObject<number> TS reports a type error even though the types of the current property would have been the same. This happens with any type, not just null (e.g. if the definition of current was T | string.

🙂 Expected behavior

Since the current properties are equivalent after substituting the generic parameters, there should be no error. It seems like TS is stopping as soon as it sees RefObject<number | null> vs RefObject<number> even though substituting the generic parameter would result in the same type. This can be confirmed by creating a copy of the RefObject type like this:

interface RefObject<T> {
    current: T | null
}

interface RefObject2<T> {
    current: T | null
}

declare function test(x: RefObject<number>): void;
declare function getRef(): RefObject2<number | null>;

let v = getRef();
test(v);

Playground

Additional information about the issue

This affects the change in React's types between version 18 and 19, where the RefObject type changed current from T | null to only T. The uses of RefObject should add null instead, e.g. RefObject<HTMLDivElement | null>. Making libraries compatible with both the React 18 and React 19 types is difficult due to this TS issue. If a library updates its implementation to React 19, including RefObject<HTMLElement | null> in its definitions, consumers still using React 18 types will see TS errors.

cc. @eps1lon in case you know about this

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

Führe zunächst die verlinkten TypeScript Playground-Reproduktionen aus und vergleiche die Fälle RefObject und RefObject2. Verfolge den Pfad der Typprüfung für die generische Instanziierung und die strukturelle Zuweisbarkeit; das Issue nennt keine Dateien oder Tests im Repository. Als abgeschlossen gilt die Aufgabe, wenn die äquivalenten ersetzten Eigenschaftstypen akzeptiert werden, ohne das bestehende Verhalten der generischen Typprüfung zu beeinträchtigen.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

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

Neue Issues direkt in Ihr Postfach

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