microsoft / microsoft/TypeScript

Check for missing property on union type causes failure in subsequent property checks

Aperta
#58,448 17 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Domain: check: Control Flow Help Wanted Possible Improvement
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
1g 19h
PR unite (30g)
117

Descrizione

🔎 Search Terms

"missing property", "property check", "type union", "control flow analysis"

🕗 Version & Regression Information
  • This is the behavior in every version I tried*, and I reviewed the FAQ for entries about property checks

*There was a minor change between 4.8 and 4.9 that changed the types but did not change the behavior: inference improved from never to incorrectUnionElement & Record<"key", unknown>.

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.4.5#code/FASwdgLgpgTgZgQwMZQARIPYFsAOBGVAb2FVNRigQBMMwAbAT1QQC5UwBXLAI1gG4SZCtVqNU3Npx79gAX2ChIsRCnTYcAJiKDSwmvSat2XXjAHzgEBjjSZcqALw7UAHzW48zt3c0K4HMCQIEFpUGgB9AGdsKAgAC3AAcwAKAEptMjUwSIh3HEciWWZIvIFnEDhUZIAiBGrUcDz04kzMnwA6BHaIDABlCBgktIFWsgB6MdQAPQB+ZwtMiqrq7nrGn2bnNvV27m6+gaHUkdHUCem5zIWyJZqkNbAmjNOOpH3+wbAU463xydn5gpFpUanUGo8Ns9Rh0uj0PkcTqNzgCrkCbiCVg8ni0Xjs9nDDl9hr9SMjLmR5LIgA

💻 Code
interface comp1 {
    readonly a: number;
    readonly b: number;
}

interface comp2 {
    readonly a: number;
}

type comp =
    | comp1
    | comp2

function do_something() {
    const comp = {} as comp;

    if ("a" in comp) {
        comp.a.toString();
        // ^? comp
    }

    if ("b" in comp) {
        comp.b.toString();
        // ^? comp1
    }

    if ("c" in comp) {
        comp.c.toString();
        // ^? comp & Record<"c", unknown>
    }

    if ("a" in comp) {
        comp.a.toString();
        // ^? comp2
    }

    if ("b" in comp) {
        comp.b.toString();
        // ^? comp2 & Record<"b", unknown>
    }
}
🙁 Actual behavior

Every property check after the ("c" in comp) one fails to narrow correctly if the key is one that is only defined for some of the element types of the type union. Attempting to access the property after one of these checks results in unknown. As well, the narrowed variable in subsequent conditionals is an arbitrary(?) union element.

🙂 Expected behavior

The conditionals that come after the ("c" in comp) conditional should have the same behavior as the ones before it, as they are the exact same code.

Additional information about the issue

This was initially noticed in a more complicated context with assertions, that I can include here as a secondary example. This one is even more strange, as it is a check for a property that is only defined on some of the elements of the union and it blocks its own duplicate check later.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia con il repro fornito di TypeScript Playground e confronta il narrowing dell’unione prima e dopo il controllo "c" in comp. Traccia l’analisi del flusso di controllo e la gestione dei controlli delle proprietà coinvolti nel narrowing dei tipi union. Il lavoro è concluso quando i controlli successivi eseguono il narrowing nello stesso modo dei controlli identici precedenti al test della proprietà mancante, incluso l’esempio secondario.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Specificata chiaramente
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.