Skip to content
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

Record<string, string> allows object keys of type symbol #53265

Closed
Patrick-clone opened this issue Mar 15, 2023 · 6 comments
Closed

Record<string, string> allows object keys of type symbol #53265

Patrick-clone opened this issue Mar 15, 2023 · 6 comments

Comments

@Patrick-clone
Copy link

Bug Report

When creating a object with symbols for keys and explicitly telling typescript the object should be of type Record<string, string>. Typescript fails to throw an error. Is does however throw an error when you use the symbol to acces the property in the object. But that is to late in my opinion.

🔎 Search Terms

Symbol, object keys, Record<string, string>

🕗 Version & Regression Information

V4.9.5

⏯ Playground Link

Playground link with relevant code

💻 Code

const one = Symbol('one');
const two = Symbol('two');

const obj: Record<string, string> = {
  [one]: 'first',
  [two]: 'second',
};

const a = obj[one];
obj[two] = 'foo';

🙁 Actual behavior

Does not report error when assigning a object with symbols as keys to a type Record<string, string> variable.

🙂 Expected behavior

Throwing a error when trying to assign a object with symbols for keys to a type Record<string, string> variable.

@MartinJohns
Copy link
Contributor

Duplicate of #44794. Currently symbols are exempt from excess property checks, and the assignment is valid because the types are compatible.

@fatcerberus
Copy link

For the record (...no pun intended), Record<string, T> doesn't mean "object with only string keys" (this is a common misconception). It means "object where every string key is type T". Like any other type, you can assign it an object with extra properties.

@Patrick-clone
Copy link
Author

@fatcerberus Thanks for the explanation. But is there any possible type that does mean "Object with only string keys"?
I tried out: { [key: string]: string } but gives the same result. Does that type not exist?

@MartinJohns
Copy link
Contributor

There's no way to represent such a type in TypeScript. This would require #12936.

@Patrick-clone
Copy link
Author

@MartinJohns Thank you for the response. That would be a nice feature.

@EltonLobo07
Copy link

@fatcerberus Thanks for the explanation. But is there any possible type that does mean "Object with only string keys"? I tried out: { [key: string]: string } but gives the same result. Does that type not exist?

What if you use a type like shown in the code block below? Will it work for your use case?

const one = Symbol('one');
const two = Symbol('two');

type StrKeyObj<TValue> = {
    [str: string]: TValue,
    [sym: symbol]: never
};

const obj: StrKeyObj<string> = {
  [one]: 'first',
  [two]: 'second',
};

/*
    Even though, the line below did not generate an error,
        1. property lookup on the object is safe, so `obj[one]` won't generate any runtime error, right?
        2. `a` has a type of `never` so we can't use it?
*/
const a = obj[one]; 
obj[two] = 'foo';

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants