镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

For loop wrong indexer type recognition #37639

Closed

Description

@k4hvd1

Seems that indexer type could be better recognized in for loop. Please check the code.
TypeScript Version: 3.7.x-dev.201xxxxx

Search Terms:
mapped type, keyof
Code

type SimpleType = { a: string, b: number }
let x: SimpleType = { a: "", b: 9 }
let fields: (keyof SimpleType)[] = ["a"]
for (const f of fields) {
    x[f] = x[f] // This throws TS 2322, although the type is obviously the same
}

Expected behavior:
The type of x[f] is the same as the x[f] and should be assignable.
Actual behavior:
x[f] is not assignable to x[f]
Playground Link:
example

Related Issues:
Actually the initial issue was with mapped type, but while looking for the cause and workaround I created this simple showcase. Suppose fixing this would resolve mapped type issue.

Activity

  1. RyanCavanaugh commented on Mar 27, 2020

    @RyanCavanaugh
    Member

    In general this is a correct error. You couldn't validly, for example, write this (it would sometimes corrupt the object), even though the types are the exactly the same:

    type SimpleType = { a: string, b: number }
    let x: SimpleType = { a: "", b: 9 }
    let fields: (keyof SimpleType)[] = ["a", "b"]
    for (const g of fields) {
      for (const f of fields) {
        if (Math.random() > 0.5) x[f] = x[g]
      }
    }

    See #32693

  2. typescript-bot commented on Mar 29, 2020

    @typescript-bot
    Contributor

    This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

  3. k4hvd1 commented on Apr 1, 2020

    @k4hvd1
    Author

    Your code makes sense, but it is a different case from the one I submitted.

    You proposed general case and x[g] is not assignable to x[f]. However its a bit tricky and special case should be considered. So, if the indexer is the same type than operation should be allowed.
    The type of indexer is not just its declared type, perhaps it also depends on exact instance. This is not currently checked with compiler, and this raise error for correct code , please check the code.

    type SimpleType = { a: string, b: number }
    let x,y: SimpleType = { a: "", b: 9 }
    let fields: (keyof SimpleType)[] = ["a", "b"]
    for (const g of fields) {
        for (const f of fields) {
            x[f] = x[g] //OK (Error -> and should not be allowed; type are not same: each one is string|number )
            y[f] = x[f] //Error -> but is OK (types are the same: each one is string or each one is number)
            x[f] = x[f] //Error -> but is OK (types are the same)
    
            let h = (Math.random() > 0.5) ? fields[0] : fields[1]
            y[h] = x[x] //Should be an error
            let j = f
            y[j]=x[f] //Would be nice if the complier let this compile to
      }
    }

    code link

    Proposal:

    1. add additional check while compiling that checks both type and variable in indexer

    2. add special keyword (to simplify and limit compiling effort)

      for (const f of /*keyword_of_mapped_field*/ fields)

    and implement additional indexer instance check

    1. add special keyword (to simplify and limit compiling effort)
    	y[/*keyword_of_mapped_indexer(*/f/*)*/]=  y[/*keyword_of_mapped_indexer(*/g/*)*/]

    and implement additional indexer instance check

  4. TiagoCavalcante commented on Nov 27, 2022

    @TiagoCavalcante

    Any updates on this?
    This feature would be really useful and doesn't seems to be as complicated as other new TypeScript features

  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

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions