Type unification not working for nested types

Ouverte
#36,245 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Évaluation

Difficulté
5/5
Temps estimé
Plus d'une semaine
Accessibilité débutants
30/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
À l'abandon
Stack technique
typescript
Domaine
compilers

Piste de recherche

Commencez par le Playground Link fourni et reproduisez la tâche avec les options du compilateur indiquées, en comparant TypeScript 3.3.3 à 3.5.1 et aux versions ultérieures. Suivez la manière dont les types génériques imbriqués sont unifiés et confirmez que c’est terminé lorsque le programme affiché se compile sans affaiblir les vérifications d’assignabilité sans rapport.

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

Description

Bug Domain: check: Variance Relationships

TypeScript Version: 3.7.2, 3.6.3, 3.5.1 (but not 3.3.3)

Search Terms:
type unification

Explanation for the code:
We have a collection of different document types (think Firebase's Cloud Firestore if you're familiar with that). Each document type of which has a type associated with it which contains a few fields like the document type, the backend return type, etc. Then we have a number of functions in our store that take in one of these types and use the specific fields that they need. (Some functions will look at the foo field, some will not.) It's not at all uncommon for these to be passed through lots of wrapping functions until the last level pulls out the field that it needs.

It is nice sometimes to be able to share code between two different (but similar) collection types. We can do if say their document type is the same (when two different endpoints return the same document). With recent versions of TypeScript we can only do that sharing if we expand the types at the place of definition.

Code

// A type that just pulls the foo field out of the type
type JustFoo<T extends { foo: any }> = T['foo'];

// This type is unused, but we have types like this too.
type JustOtherField<T extends { otherField: any }> = T['otherField'];

// We then wrap this in another type
type WrappedJustFoo<T extends { foo: any }> = { wrapped: JustFoo<T> };

// We then have a lot of types that have a `foo` field and `otherField` fields.
// These types will be passed into a lot of other functions, some of which
// will only use the `foo` field, where as other function may use other parts.

type Alpha = { foo: number; otherField: string };
type Beta = { foo: number; otherField: boolean };


// We can define variables then using `WrappedJustFoo`.
const alpha: WrappedJustFoo<Alpha> = { wrapped: 3 };
const beta: WrappedJustFoo<Beta> = { wrapped: 3 };

// Sadly we can't share them even though ` WrappedJustFoo<Alpha>` and
// `WrappedJustFoo<Beta>` actually resolve to the same type.
const beta2: WrappedJustFoo<Beta> = alpha;

// If we use the resolved type we can convert either way.
let gamma: { wrapped: number } = alpha;
let beta3: WrappedJustFoo<Beta> = gamma;

Expected behavior:
The program compiles.

Actual behavior:

Type 'WrappedJustFoo<Alpha>' is not assignable to type 'WrappedJustFoo<Beta>'.
  Type 'Alpha' is not assignable to type 'Beta'.
    Types of property 'otherField' are incompatible.
      Type 'string' is not assignable to type 'boolean'.(2322)

It makes sense that if you want to check that 'WrappedJustFoo<Alpha>' is assignable to type 'WrappedJustFoo<Beta>' you only check if 'Alpha' is assignable to type 'Beta', but this isn't the only way they can be compatible.

Related Issues: Nothing jumps out at me. #30134 maybe?

Compiler Options
{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "useDefineForClassFields": false,
    "alwaysStrict": true,
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    "downlevelIteration": false,
    "noEmitHelpers": false,
    "noLib": false,
    "noStrictGenericChecks": false,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "esModuleInterop": true,
    "preserveConstEnums": false,
    "removeComments": false,
    "skipLibCheck": false,
    "checkJs": false,
    "allowJs": false,
    "declaration": true,
    "experimentalDecorators": false,
    "emitDecoratorMetadata": false,
    "target": "ES2017",
    "module": "ESNext"
  }
}

Playground Link: Provided

Langage dominant
Go
Étoiles
111k
Forks
14.4k
Merge moyen
1 j 19 h
PR mergées (30 j)
117

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.

Autres issues de microsoft/TypeScript

Toutes les issues de microsoft/TypeScript

Issues similaires

Plus d'issues Go

Recevez les nouvelles issues par e-mail

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