-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Type of record value assigned to template literal computed property name is not checked if it follows a spread of the record #45798
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
As a temporary workaround: Writing |
It does ! I actually create the key from a function that returns the constructed string type, and you can't "as const" a function return value. Forcing the type ("as PersonKey") does not work either. type PersonKey = `person-${Person["id"]}`;
function personKey(id: number): PersonKey {
return `person-${id}`;
} I simplified it as much as I could for the report. The workaround I'm using is to assign the value to an explicitly-typed variable first, then assign this variable to the attribute: /* When using computed properties as object key, TS does not check value type.
https://github.com/microsoft/TypeScript/issues/45798
DO NOT INLINE THAT ASSIGNMENT
*/
const myPerson: Person = { id: 1, name: "" };
persons = {
...persons,
[personKey(1)]: myPerson /* see comment on myPerson */,
} The type is still not checked on assignment in |
This is a side effect of template literals having type A few possibilities come immediately to mind
|
I think I imagined that template literals as computed property names should be as narrow as possible, but I probably was overconfident about that when labeling it a bug. In hindsight, I think this should be Suggestion / Awaiting More Feedback or In Discussion. Iβm pretty sure calling it a bug is too optimistic and calling it a design limitation is too pessimistic. I think we could change the behavior if we were confident it's worth the tradeoffs. |
Another option:
const x: `person-${Person["id"]}` = `person-${1}` |
I experimented with a couple of implementations. I'll write up my notes on a PR. |
By analogy with the existing rule that element access argument expressions are a const context. Fixes #45798
I just noticed something similar and am 99% sure it's the same issue, although I think I might have come up with a weird ish edge case? (If this is a separate issue, please let me know and I'll make a new issue). In the below code/playground link I find it interesting how The const users = ['frank', 'charles', 'bob', 'whitney', 'richard'];
interface UsersParams {
[key: `username.${number}`]: string;
}
const withImplicit = users.reduce<UsersParams>((acc, cur, index) => ({
...acc,
[`username.${index}`]: cur,
[`no.${index}`]: cur,
[`no.5`]: cur
}), {});
const withExplicitAssign = users.reduce<UsersParams>((acc, cur, index) => {
acc[`username.${index}`] = cur;
acc[`no.${index}`] = cur; // Element implicitly has an 'any' type because expression of type '`no.${number}`' can't be used to index type 'UsersParams'.(7053)
acc[`no.5`] = cur; // Element implicitly has an 'any' type because expression of type '"no.5"' can't be used to index type 'UsersParams'. Property 'no.5' does not exist on type 'UsersParams'.(7053)
return acc;
}, {});
const withExplicitSpread = users.reduce<UsersParams>((acc, cur, index) => {
acc = {
...acc,
[`username.${index}`]: cur,
[`no.${index}`]: cur,
[`no.5`]: cur // Type '{ "no.5": string; }' is not assignable to type 'UsersParams'. Object literal may only specify known properties, and '[`no.5`]' does not exist in type 'UsersParams'.(2322)
}
return acc;
}, {}); |
This issue appears to be fixed and can probably be closed? Seems like some change in 5.2.x addressed it, though I don't see it mentioned in the release notes. |
It looks like it yes. If I stumble upon it again on any project with TS > 5.2.x I'll reopen. |
Bug Report
π Search Terms
assignment check type record template literal index spread
π Version & Regression Information
β― Playground Link
Playground link with relevant code
π» Code
π Actual behavior
No error on the assignment on last line.
π Expected behavior
There should be a type error because the object being assigned is not a
Person
.Error triggers correctly in any of the following scenarios:
{ "person-1": {/* error triggers correctly */}
), or a "simple" computed property (e.g.{ ["person-1"]: {/* error triggers correctly */}
)Still, thank you all for the great language !
The text was updated successfully, but these errors were encountered: