Repository: TypeScript
Issue: { [Symbol.toPrimitive]: () => Symbol }: support as index/property type
Labels: Suggestion,Awaiting More Feedback

# Suggestion

<!--
  Please fill in each section completely. Thank you!
-->

## 🔍 Search Terms

<!--
  💡 Did you know? TypeScript has over 2,000 open suggestions!
  🔎 Please search thoroughly before logging new feature requests as most common ideas already have a proposal in progress.
  The "Common Feature Requests" section of the FAQ lists many popular requests: https://github.com/Microsoft/TypeScript/wiki/FAQ#common-feature-requests

  Replace the text below:
-->

- `Symbol.toPrimitive`
- `unique symbol`

## ✅ Viability Checklist

<!--
   Suggestions that don't meet all these criteria are very, very unlikely to be accepted.
   We always recommend reviewing the TypeScript design goals before investing time writing
   a proposal for ideas outside the scope of the project.
-->
My suggestion meets these guidelines:

* [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).


## ⭐ Suggestion

<!-- A summary of what you'd like to see added or changed -->

1. Instead of receiving `A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.` I want to be able to use types with `[Symbol.toPrimitive]` methods as properties in an interface.
1. Instead of receiving `A computed property name must be of type 'string', 'number', 'symbol', or 'any'.` I want to be able to use a value with a `[Symbol.toPrimitive]` method as a property name.
1. Instead of receiving `Type 'SomeType' cannot be used as an index type.` I want to be able to use a value with a `[Symbol.toPrimitive]` method as an index type.

## 📃 Motivating Example

<!--
  If you were announcing this feature in a blog post, what's a short explanation that shows
  a developer why this feature improves the language?
-->

```ts
class UniquePerson {
  #symbol = Symbol();
  constructor(readonly name: string) {}
  [Symbol.toPrimitive]() {
    return this.#symbol;
  }
}
const sherlock = new UniquePerson("Sherlock Holmes");
interface PersonToAddress {
  [sherlock]: string;
  // ^ A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.
}
const personToAddress: PersonToAddress = {
  [sherlock]: "221B Baker Street",
  // ^ A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
};
personToAddress[sherlock]; //=> 221B Baker Street
               // ^ Type 'UniquePerson' cannot be used as an index type.
```

## 💻 Use Cases

<!--
  What do you want to use this for?
  What shortcomings exist with current approaches?
  What workarounds are you using in the meantime?
-->

I am working on a library that heavily uses `Symbol`s to add extension function to other types while avoiding name conflicts (as `Symbol`s are unique). Instead of passing around `Symbol`s directly I want to pass around richer objects with more information but, when passed in as an index type, I want the `[Symbol.toPrimitive]` functions on my richer objects to be called and resolve to the appropriate `Symbol`. Currently I am exploring either not supporting TypeScript initially (which is not ideal and could inhibit adoption) or ditch the idea of passing around richer objects and use `Symbol`s directly (but this greatly reduces the usability and usefulness of the library).