microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.07k stars 12.37k forks source link

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record<...>' #45912

Closed predragnikolic closed 2 years ago

predragnikolic commented 2 years ago

Bug Report

Given the following code:

type Personality = "social" | "positive" | "enthusiastic"
type Result = {value: number}

type PersonalityRecord = Record<Personality, Result>

export function doStuff(personalityRecord: PersonalityRecord) {
  for (const personality in personalityRecord) {
    const result = personalityRecord[personality]
               //  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record<Personality, Result>'. No index signature with a parameter of type 'string' was found on type 'Record<Personality, Result>'.
  }
}

πŸ™ Actual behavior

TypeScirpt is reporting an error.

Error: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record<Personality, Result>'. No index signature with a parameter of type 'string' was found on type 'Record<Personality, Result>'.

Typescript thinks that personality is of type string, but I expect it to be of type Personality.

πŸ™‚ Expected behavior

Typescript should not report the error and the above code should just work.

Here is the CodeSandBox example: https://codesandbox.io/s/young-night-516gs?file=/src/index.ts:268-346

My current workaround is to use a cast const result = personalityRecord[personality as Personality], but I don't like that. Is there a more nicer way to solve this?

fatcerberus commented 2 years ago

This is for the same reason Object.keys() returns string[]: https://stackoverflow.com/questions/55012174/why-doesnt-object-keys-return-a-keyof-type-in-typescript

Your PersonalityRecord object isn't guaranteed (by the type system) to only contain Personality keys, and in turn those extra properties are not guaranteed to be of type Result.

andrewbranch commented 2 years ago

Duplicate of https://github.com/microsoft/TypeScript/issues/35847

predragnikolic commented 2 years ago

Thanks @fatcerberus , now it is clear why typescript behaves like this.

Having an Exact type would solve my issue, but until something like that exist I would have to stick with casting.

Have a nice day. πŸ‘‹