-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Template literal index does not transform the key and value types. #48983
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
Comments
I think the error message is misleading. Looks like the compiler can't see that As evidence that the compiler is definitely able to recognize that you are indexing into function getPreferenceNonGeneric(key: keyof PreferencesSchema): PreferencesSchema[keyof PreferencesSchema] {
return data[`preferences.${key}`]; // okay
} So the problem is the abstract relationship between It seems like this is related to #30581, but I can't see a reasonable way to make the fix in #47109 help here. |
This is broken in the same way in 4.3 if you add an return data[`preferences.${key}` as const]; The error message is indeed super wrong. It seems like we're trying to relate |
So the reported error here comes from this check and this check doesn't have a chance to be satisfied here: This is not the only check that is performed here because if this fails then the constraint-based fallback is used~: This check doesn't succeed either because the computed
There is some heuristic in place that makes the first error to be displayed here - but this somewhat doesn't matter as the second one is almost as confusing as the first one :p So... how this potentially could be fixed? I think that instead of checking |
This is working as intended. What's missing in the example is the presence of a mapped type to demonstrate the relationship between type PreferencesSchema = {
a: string,
b: number,
}
type DataSchema<T> = { [P in keyof T as `preferences.${P & string}`]: T[P] }
const data: DataSchema<PreferencesSchema> = {
"preferences.a": "hello world",
"preferences.b": 12345
}
function getPreference<K extends keyof PreferencesSchema>(key: K) {
return data[`preferences.${key}`];
} |
@ahejlsberg how the demonstrated relationship helps conceptually cases like this? type of I also think that your example is closer to the presented workaround ( type PreferencesSchema = {
a: string,
b: number,
}
type DataSchema<T> = { [P in keyof T as `preferences.${P & string}`]: T[P] }
const data: DataSchema<PreferencesSchema> = {
"preferences.a": "hello world",
"preferences.b": 12345
}
function getPreference<K extends keyof PreferencesSchema>(key: K): PreferencesSchema[K] {
// Type 'DataSchema<PreferencesSchema>[`preferences.${K}`]' is not assignable to type 'PreferencesSchema[K]'.
// Type 'DataSchema<PreferencesSchema>' is missing the following properties from type 'PreferencesSchema': a, b
return data[`preferences.${key}`];
} Note that the annotated return type is referring to the |
Hmm, I missed that the type annotation is using an indexed access on the original type instead of the mapped type. I think it is bit of a stretch to expect that to type check. Specifically, given non-generic object types |
Ye, I see how it gets pretty gnarly for the compiler - from the user's perspective it isn't that obvious that this might be the limitation (in such cases it usually isn't obvious because we, users, have no idea how the compiler works under the hood) and the reported error is quite confusing. Perhaps at least this error could be improved?
Right, this is a good example of how to make the relationship more explicit and "sync" both of those schema types over time. |
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
Hm, should the bot close after 3 days since the last comment? That seems to be... pretty fast 😬 |
Bug Report
I have a data store that uses prefixes to store different types of data. One of the types is "preferences".
I have a getter interface for preferences that allows the user to query without the prefix:
Unfortunately, this gives an error, because TS looks for
a
andb
on thedata
instead of the actual indexespreferences.a
andpreferences.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
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
🙁 Actual behavior
An error occurs:
🙂 Expected behavior
TypeScript should recognize that
preferences.a
/preferences.b
is being used as an index, nota
/b
. Therefore it shouldn't matter thatDataSchema
is missinga
andb
as properties.The text was updated successfully, but these errors were encountered: