Skip to content

Inferring type from Record where keys are template literal types should return correct value type #42159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
minheq opened this issue Dec 30, 2020 · 9 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@minheq
Copy link

minheq commented Dec 30, 2020

Bug Report

πŸ”Ž Search Terms

  • record template literal types [infer]
  • record template literal key
  • template literal types

Found #29718 but not sure if it is the same error

πŸ•— Version & Regression Information

TypeScript v4.2.0-dev.20201230

⏯ Playground Link

https://www.typescriptlang.org/play?ts=4.2.0-dev.20201230#code/PTAEBcE8AcFNQMIHsA2SBOoC8oDO50BLAOwHNQRQAVAC0N1AHcMBrXAKCjkVQ21AAGAY17oAJAG98RMgF8BnGPGRp0DHACVYI9ABMAPCowAaPARKkAfAG527EcXygRq3AC4er-hPag-oAHIXDAAhFABXWACPALDIgONff0oAZRokcJRdUGh0JABbaHBQWHQ89AB+JL8AkgA3AEMUQl1owK1WxNk7ShCAVQBxADpnUVASADNShnAkQXDiFiRGYgFxx3BYBuykCcFpCwEh+yQN0dV+UlhwAGlYSAA1JsiACmC1UyDROKiASjsJgshOBCKdQFdbvcnhFYPoklQSgAPTbEXQMLQ6AwHMimBYsYjLYiWRJ+G5IlFo0Ase67ajsSwvJAAIwAVh4qKZqZAPDdfuyANo3AC6oB8fnQ13C6GIoGZLP5XKFtm6QA

πŸ’» Code

// type Color = string // This works
type Color = `color${string}`
type Colors = Record<Color, string>;

const colors: Colors = {
    'colorBlue': 'Blue',
    // BUG. should prompt error?
    'invalid': 'Red',
}

// BUG. color infers to `unkown` instead of `string`.
const color = getKeyValue(colors, 'colorBlue')

function getKeyValue<
  T extends Record<string, unknown>,
  K extends keyof T
>(obj: T, key: K): T[K] {
  return obj[key];
}

πŸ™ Actual behavior

  • getKeyValue(colors, 'colorBlue') infers unknown
  • 'invalid': 'Red', is still valid key for colors: Colors

πŸ™‚ Expected behavior

  • getKeyValue(colors, 'colorBlue') should infer string return value
  • 'invalid': 'Red', should prompt an error as it does not match template literal type
@andrewbranch andrewbranch added the Working as Intended The behavior described is the intended behavior; this is not a bug label Dec 30, 2020
@andrewbranch
Copy link
Member

The definition of Record is

type Record<K extends keyof any, T> = {
    [P in K]: T;
};

which is a mapped type that creates a property for every constituent of K if K is a literal type that can be used as a property name, or a union of those. E.g., Record<'one' | 'two', string> is equivalent to { one: string, two: string }. If K can instead be used as an index signature, it will do that instead, e.g. Record<number, string> is equivalent to { [key: number]: string }. Template literal types cannot be property names (since they can stand for an infinite number of property names), and currently, only string and number can be used as an index signature. So the mapped type can’t do anything and falls back to {}. (You can hover Colors in your playground and see this.)

This will be fixed if #26797 is merged, because template literal types will be allowed as an index signature parameter.

@minheq minheq closed this as completed Dec 31, 2020
@minheq
Copy link
Author

minheq commented Dec 31, 2020

@andrewbranch thanks for clear explanation! i hope the PR will eventually get merged :D

@andrewbranch
Copy link
Member

Me too! πŸ˜„

@kkmuffme
Copy link

kkmuffme commented Dec 7, 2022

@andrewbranch could this issue be reopened?
The PR was superseded by another one, however this "bug" is still here

@andrewbranch
Copy link
Member

❓ The expected behavior in the original repro is now the actual behavior.

image

@andrewbranch
Copy link
Member

andrewbranch commented Dec 7, 2022

Yeah, because that’s the version of TypeScript that we were on when the issue was reported πŸ˜„

@kkmuffme
Copy link

kkmuffme commented Dec 7, 2022

🀣 ah sorry, I thought it would take the latest by default

@andrewbranch
Copy link
Member

Haha no worries, I think it depends on whether or not the TS version is explicitly encoded into the URL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

3 participants