microsoft / microsoft/TypeScript

Regression of `this is` type predicate for intersection of unions from 4.7 to 4.8

Ouverte
#63,039 4 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Bug Domain: This-Typing Needs Human Review
Langage dominant
Go
Étoiles
111k
Forks
14.3k
Merge moyen
2 j 4 h
PR mergées (30 j)
132

Description

🔎 Search Terms

"this is" "type predicate" "intersection" "union"

🕗 Version & Regression Information
  • This changed between versions 4.7.4 and 4.8.4
⏯ Playground Link

https://www.typescriptlang.org/play/?ssl=40&ssc=1&pln=1&pc=1#code/PTAEF5NBlBRAVAqgBQFABcCeAHApqRbAEwEN19xQBvUAV2LNwH0BLIgLlADtaBbAI1wAnUAF8A3KgDGAGxIBneaADCAey7kAHumqpQ+0FPXz0Q2lPSqhACmy1+MllLoNynQqXIBKaqL0GpAAtcKQBray9OdECWJViVYLDcIl0DNNAhXHRaIS5QU1pcSTS-Pyw8BJDQ5IhqF09cThoAJVgAWQB5ADVYJngACQBJaD6OpgAxQYANAH5OLlwAN2ExMUlUEAgoeABNZFhQNoBBAHFB5QwcfHGWGXIhNQ1cbQAeZVBn8i4iJUetdAANKAAIofbS4b5KExCFhcADmAD5ashhAAzKy8YGFISYF7+fTKAH40DNWhcLHCXHAhGoBGSTYkbDYGSYUAkUAAR2xrMy8lod1A-FZsPu8hC6FhcNALB0AHcZYECK5cECSN98sE8rCAFbiyXSjSqFSXCoooTooSY7lvMFfH4qdT-IGIW0Q+2qfi6ixIyguz5upRk0JcVSyrjEmYqUAAMjq9Aa7mVMYIYmJ8yWwkk5XwpPJ1tB-shoGhkp9DoEsNwLyOimE6AA0rgqQigdSs1dQDWxUIG02XgXwUWS-CywO7YGuMHQ+G0pHmiErER+0CAHLqFf8uQOKtBkNhhE0tLp5ZCdabIi4VGVtlEIgyljqEgyUBX3Ayd15F3y6KgRZPwqgAABmSF5XgsRCASa+BqBWCwvIgQL1q6Q6mKWtR+oO9q7tOEYprGyAkD2LBPi885GEIS6wJosi0BeLz1kC1SYKoqIEC2dDfJelZEAeabcBmp6oBsYCQJQ-QdAA6qAgzwKAABCrRHPW0CoBesiEfgRhcCYhjoJonA3Hcwh-J8eJpIZ9wma8VmAqAABE6i4HZoAAD72egsqqHZLbEnZHlebSkhaTpnlCKESiUBYmgAHTxowsXKqwRDthUElWOFtTWNmLG6ZoybKIk1REF4ADadlxeQdkALplRVzBsNVkgsKx1hRdFQRVBEPhUMSwU6PwmQkBlkV6QlDRjYwSWSH4QA

💻 Code
// === SETUP
type Update = { update_id: number };
class Context {
    constructor(public update: Update) {}
    check(): this is Checked {
        return true;
    }
}
type Checked = { update: { REMOVE_THIS_TO_FIX?: never } };

// === TYPE MAGIC
type FilterContext<C extends Context, Q extends string> = PerformQuery<
    C,
    RunQuery<Q>
>;
// apply a query result by intersecting it with Update, and then injecting into C
type PerformQuery<C extends Context, U extends object> = U extends unknown
    ? C & { update: Update & U }
    : never;
type RunQuery<Q extends string> = Combine<AssertKey<Q>, Q>;
type AssertKey<Q extends string> = Q extends unknown
    ? Record<Q, NonNullable<unknown>>
    : never;

// define additional fields on U with value `undefined`
type Combine<U, K extends string> = U extends unknown
    ? U & Partial<Record<Exclude<K, keyof U>, undefined>>
    : never;

// === HOW IT BREAKS
declare const ctx: FilterContext<
    FilterContext<Context, "one" | "two">,
    "two"
>;
const works = ctx.update.update_id;
type Works = (typeof ctx & Checked)["update"]["update_id"];
if (ctx.check()) {
    const breaks = ctx.update.update_id;
}
🙁 Actual behavior

In the line where the variable breaks is defined, ctx.update is never

🙂 Expected behavior

The variable breaks can be defined and it has type number

Additional information about the issue

If you change a seemingly unrelated piece in the code, the error goes away!

// Replace
type Checked = { update: { REMOVE_THIS_TO_FIX?: never } };
// by
type Checked = { update: { } };

and then everything works as expected.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par le TypeScript Playground lié et comparez la reproduction sur 4.7.4 et 4.8.4. Suivez la réduction effectuée par Context.check() pour l’exemple FilterContext<Context, "one" | "two">. Le travail est terminé lorsque l’accès à breaks est accepté et inféré comme number, et que la régression est couverte par un test.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
typescript
Domaine
compilers
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
Calme
Clarté
Plutôt claire
Accessibilité débutants
38/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.