Skip to content

Nested Mapped Type Doesn't Cause Error for Mismatch enum when Single Mapped Type Does #45530

Closed

Description

@wilwade

Bug Report

🔎 Search Terms

nested mapping, generic type with enum matching, mapped type over another mapped type

🕗 Version & Regression Information

This is the behavior in every version I tried (all playground versions), and I reviewed the FAQ for entries about nested mapped types.

⏯ Playground Link

Playground link with relevant code

💻 Code

enum ABC { A, B, C }

type Gen<T extends ABC> = { v: T; }

type Gen2<T extends ABC> = {
  [Property in keyof Gen<T>]: { s: string };
};

type MappedAbcToGen = {
  [T in ABC]: Gen<T>;
};

const genTypeA: Gen<ABC.A> = { v: ABC.A };
const genTypeB: Gen<ABC.B> = { v: ABC.B };
const genTypeC: Gen<ABC.C> = { v: ABC.C };

// Correct Failure
const thingWithMapped: MappedAbcToGen = {
  [ABC.A]: genTypeB, // Correct failure! Require Matching!
  [ABC.B]: genTypeB, // Good. Matching
  [ABC.C]: genTypeC, // Good. Matching
}

type MappedAbcToGen2 = {
  [T in ABC]: Gen2<T>;
};

const gen2TypeA: Gen2<ABC.A> = { v: { s: "I am A" } };
const gen2TypeB: Gen2<ABC.B> = { v: { s: "I am B" } };
const gen2TypeC: Gen2<ABC.C> = { v: { s: "I am C" } };

// Incorrect Failure
const thingWithMappedTwiceConsTyped: MappedAbcToGen2 = {
  [ABC.A]: gen2TypeB, // Want failure. Require Matching!
  [ABC.B]: gen2TypeB, // Good. Matching
  [ABC.C]: gen2TypeC, // Good. Matching
}

🙁 Actual behavior

It did NOT have an error on the double mapped type:
[ABC.A]: gen2TypeB should throw an error as it does for MappedAbcToGen with [ABC.A]: genTypeB

🙂 Expected behavior

Same error as with the single mapped type:

[ABC.A]: gen2TypeB should throw an error and require [ABC.A]: gen2TypeA so that the T matches as MappedAbcToGen2 implies and works for MappedAbcToGen

Thanks for looking!

Activity

  1. wilwade commented on Aug 21, 2021

    @wilwade
    Author

    I realized that perhaps the lack of an error comes from the type not being different at that point in time. Here is an adjusted playground

    However, it still does not trigger the error, even with the type being even more wrong.

    enum ABC { A, B, C }
    
    type Gen<T extends ABC> = { v: T; } & (
      {
        v: ABC.A,
        a: string,
      } | {
        v: ABC.B,
        b: string,
      } | {
        v: ABC.C,
        c: string,
      }
    )
    
    type Gen2<T extends ABC> = {
      [Property in keyof Gen<T>]: { s: string };
    };
    
    type MappedAbcToGen = {
      [T in ABC]: Gen<T>;
    };
    
    const genTypeA: Gen<ABC.A> = { v: ABC.A, a: "x" };
    const genTypeB: Gen<ABC.B> = { v: ABC.B, b: "y" };
    const genTypeC: Gen<ABC.C> = { v: ABC.C, c: "z" };
    
    // Correct Failure
    const thingWithMapped: MappedAbcToGen = {
      [ABC.A]: genTypeB, // Correct failure! Require Matching!
      [ABC.B]: genTypeB, // Good. Matching
      [ABC.C]: genTypeC, // Good. Matching
    }
    
    type MappedAbcToGen2 = {
      [T in ABC]: Gen2<T>;
    };
    
    const gen2TypeA: Gen2<ABC.A> = { v: { s: "I am A" }, a: { s: ""} };
    const gen2TypeB: Gen2<ABC.B> = { v: { s: "I am B" }, b: { s: ""} };
    const gen2TypeC: Gen2<ABC.C> = { v: { s: "I am C" }, c: { s: ""}  };
    
    // Incorrect Failure
    const thingWithMappedTwiceConsTyped: MappedAbcToGen2 = {
      [ABC.A]: gen2TypeB, // Want failure. Require Matching!
      [ABC.B]: gen2TypeB, // Good. Matching
      [ABC.C]: gen2TypeC, // Good. Matching
    }
  2. andrewbranch commented on Aug 23, 2021

    @andrewbranch
    Member

    Slightly reduced with some breadcrumbs added: playground

    enum ABC { A, B }
    
    type Gen<T extends ABC> = { v: T; } & (
      {
        v: ABC.A,
        a: string,
      } | {
        v: ABC.B,
        b: string,
      }
    )
    
    // Quick info: ???
    //
    // type Gen2<T extends ABC> = {
    //    v: string;
    // }
    //
    type Gen2<T extends ABC> = {
      [Property in keyof Gen<T>]: string;
    };
    
    // 'a' and 'b' properties required
    const gen2TypeA: Gen2<ABC.A> = { v:  "I am A", a: "" };
    const gen2TypeB: Gen2<ABC.B> = { v:  "I am B", b: "" };
    
    // 'v' ???
    type K = keyof Gen2<ABC.A>;
    
    // :(
    declare let a: Gen2<ABC.A>;
    declare let b: Gen2<ABC.B>;
    a = b;
    b = a;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Fix AvailableA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.RescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions