microsoft / microsoft/TypeScript

{} and { [K in never]: any } exhibit different simplification behavior

Ouverte
#42,864 3 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Bug Domain: Mapped Types
Langage dominant
Go
Étoiles
111k
Forks
14.3k
Merge moyen
1 j 19 h
PR mergées (30 j)
117

Description

Bug Report

Under some circumstances, TypeScript treats { [K in never]: any } & { foo?: number } differently than {} & { foo?: number }. However, this does not occur with { [K in never]: any } & { foo: number }.

🔎 Search Terms

empty mapped object type, intersection with optional object, K in never

🕗 Version & Regression Information

Tested on 4.0.5, 4.1.5, 4.2.0-beta, and the current nightly

⏯ Playground Link

Playground link

💻 Code
type AreAllStringsTs<T> = string extends T ? true : false;
type Test1 = AreAllStringsTs<{ foo?: number }>;                         // expected: false, actual: false
type Test2 = AreAllStringsTs<{ foo: number }>;                          // expected: false, actual: false
type Test3 = AreAllStringsTs<string | number>;                          // expected: true,  actual: true
type Test4 = AreAllStringsTs<{ [K in never]: any } & { foo?: number }>; // expected: false, actual: true  <-- FAIL
type Test5 = AreAllStringsTs<{ [K in never]: any } & { foo: number }>;  // expected: false, actual: false
🙁 Actual behavior

Test4 is true.

🙂 Expected behavior

Test4 is false.

Potential Workaround

If you have a mapped object type in which the type expression for the keys might reduce to never, add a conditional check to see if the keys set is empty. For example, I encountered this when working with a type that would make all keys of an object that could take on the value undefined optional:

type Optionalize<T> =
    { [K in RequiredKeys<T>]: T[K] }
    & { [K in NonRequiredKeys<T>]?: T[K] };

Adding a check for never made the behavior consistent with what I was expecting when every field of the input type accepted undefined:

type Optionalize<T> =
    (RequiredKeys<T> extends never ? {} : { [K in RequiredKeys<T>]: T[K] })
    & { [K in NonRequiredKeys<T>]?: T[K]; };

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 lien Playground fourni et reproduisez la différence entre Test4 et Test5. Suivez la manière dont le compilateur simplifie le type mappé vide lorsqu’il est intersecté avec des types d’objet optionnels et requis. C’est terminé lorsque Test4 est évalué à false, tandis que les autres attentes signalées restent inchangées.

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é
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

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