Skip to content

Template literal index does not transform the key and value types. #48983

Closed
@benjaminpjones

Description

@benjaminpjones

Bug Report

I have a data store that uses prefixes to store different types of data. One of the types is "preferences".

data = {
  "preferences.a": string,
  "preferences.b": number
}

I have a getter interface for preferences that allows the user to query without the prefix:

type PreferencesSchema = {
  a: string,
  b: number
}
function getPreference<KeyT extends keyof PreferencesSchema>(key: KeyT): PreferencesSchema[KeyT] {
  return data[`preferences.${key}`];
} 

Unfortunately, this gives an error, because TS looks for a and b on the data instead of the actual indexes preferences.a and preferences.b. I understand template literal types are relatively new, but I think in this case, the compiler should see that the prefixed keys are being used and that the associated values are the same as the value types in the preference schema.

I found a similar looking issue: #13948, but I don't think this error can be attributed to type-widening.

🔎 Search Terms

template literal missing properties

🕗 Version & Regression Information

  • This changed between versions 4.3.5 and 4.4.4 (4.3.5 still gives a noImplicitAny error, but the introduction of template literal types makes this issue arise even without strict checks)

⏯ Playground Link

Playground link with relevant code

💻 Code

type PreferencesSchema = {
  a: string,
  b: number
}

interface DataSchema {
  "preferences.a": string,
  "preferences.b": number
}

const data: DataSchema = {
  "preferences.a": "hello world",
  "preferences.b": 12345
}

// the issue
function getPreference<KeyT extends keyof PreferencesSchema>(key: KeyT): PreferencesSchema[KeyT] {
  return data[`preferences.${key}`];
} 

// workaround
function workingGetPreference<KeyT extends keyof PreferencesSchema>(key: KeyT): DataSchema[`preferences.${KeyT}`] {
  return data[`preferences.${key}`];
}

🙁 Actual behavior

An error occurs:

Type 'DataSchema[`preferences.${KeyT}`]' is not assignable to type 'PreferencesSchema[KeyT]'.
  Type 'DataSchema' is missing the following properties from type 'PreferencesSchema': a, b

🙂 Expected behavior

TypeScript should recognize that preferences.a/preferences.b is being used as an index, not a/b. Therefore it shouldn't matter that DataSchema is missing a and b as properties.

Metadata

Metadata

Assignees

Labels

Working as IntendedThe behavior described is the intended behavior; this is not a bug

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions