Skip to content

No-op mapped type not assignable; but original type is assignable #38235

Closed

Description

@AnyhowStep

TypeScript Version: 3.8.3

Search Terms:

no-op mapped type, assignable

Code

type Foo<IdentifierT extends Record<PropertyKey, PropertyKey>> =
    IdentifierT
;

type Bar<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
    {
        [k in keyof T] : Foo<IdentifierT & { k : k }>
    }
;

type Merge2<T> = { [k in keyof T] : T[k] }
type Bar2<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
    {
        [k in keyof T]: Foo<Merge2<IdentifierT & { k: k }>>
        //                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //                  Works in 3.5.1
        //                  Works in 3.6.3
        //                  Works in 3.7.5
        //                  Fails in 3.8.3
    }
;

type Identity<T> = T;
type Merge3<T> = Identity<{ [k in keyof T] : T[k] }>
type Bar3<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
    {
        [k in keyof T]: Foo<Merge3<IdentifierT & { k: k }>>
        //                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //                  Works in 3.5.1
        //                  Works in 3.6.3
        //                  Works in 3.7.5
        //                  Fails in 3.8.3
    }
;

Expected behavior:

Passes type checking

Actual behavior:

Fails in TS 3.8.3

Playground Link:

Playground

Related Issues:

Not that I could find


Well, it isn't exactly a "no-op" mapped type.

It will strip call and constructor signatures, but "no-op mapped type" was the best name I had for it.

Activity

  1. phiresky commented on May 16, 2020

    @phiresky

    I think I have the same issue with https://github.com/phiresky/ts-typed-sql, which destroys type inference everywhere, means our whole project is stuck on 3.7 for now :(

  2. AnyhowStep commented on May 21, 2020

    @AnyhowStep
    ContributorAuthor

    I've been stuck at 3.5.1 forever now =(

  3. phiresky commented on May 23, 2020

    @phiresky

    I just bisected the ts compiler to find the cause using

    build.sh

    #!/bin/bash
    set -e -x
    bisect_error=125
    
    yarn install --silent || exit $bisect_error
    gulp -L local || exit $bisect_error
    
    node built/local/tsc.js --noEmit ../example.ts
    git bisect start v3.8.3 v3.7.5
    git bisect run ../build.sh
    

    bisect reports:

    first bad commit: [357f715] Check combined intersection properties against target index signatures (#35143) by Anders Hejlsberg (@ahejlsberg)

  4. ahejlsberg commented on May 24, 2020

    @ahejlsberg
    Member

    A simpler repro for this issue:

    type Same<T> = { [P in keyof T]: T[P] };
    
    type Foo<T extends Record<PropertyKey, number>> = T;
    
    type Bar<T extends Record<PropertyKey, number>> = Foo<Same<T>>;  // Error

    We shouldn't error above and strangely we don't if the declaration of Foo is changed to

    type Foo<T extends Record<string, number>> = T;

    That's definitely a bug.

    The example above worked before #35143 because we were very lax in our checking of relations involving intersections on the source side.

  5. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions