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

[Feature Request] Provide syntax for exceptions to index operator #38977

Closed
5 tasks done
thw0rted opened this issue Jun 8, 2020 · 3 comments
Closed
5 tasks done

[Feature Request] Provide syntax for exceptions to index operator #38977

thw0rted opened this issue Jun 8, 2020 · 3 comments
Labels
Duplicate An existing issue was already created

Comments

@thw0rted
Copy link

thw0rted commented Jun 8, 2020

Search Terms

index signature class extend record

Suggestion

Come up with some syntax for classes to implement a Record pattern / index signature, while having members/methods that do not conform to its constraints.

class FooDictionary {
  [key: string, other than "id" or "print" or "serialize"]: Foo;  // Needs magic
  id: string;
  print() { ... }
  serialize() { ... }
}

I'm not sure how this would be implemented. Maybe what's needed is a "complement" type, i.e. a formal internal representation of Exclude<string, "a" | "b"> that doesn't just collapse down to string?

Use Cases

There seems to be wide consensus that implementing the Record pattern directly on classes is A Bad Idea, but that doesn't change the fact that legacy codebases exist that use this pattern. I came here because I'm trying to describe the shape of this PropertyBag class but there are a bunch of StackOverflow questions (and a few issues here) where people are asking for the same thing

Details

I've done pretty extensive research and have found a number of partial workarounds, but none that fully describe a type that:

a) is new-able,
b) types its unknown properties strongly, and
c) types is known properties correctly

The closest I've gotten is this union type where you declare a base class and an interface with an index signature, then declare a union type that mashes them together, but as the Playground example shows, that union isn't new-able.

(Moving the bag-of-values down to a member property, would be a good idea, but I'm trying to describe the shape of code I don't own.)

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.
@j-oliveras
Copy link
Contributor

Related/duplicate #4183, #4196 and #29317

@thw0rted
Copy link
Author

thw0rted commented Jun 8, 2020

Thanks @j-oliveras , I didn't have the right terminology for "negated" -- "complement" turned up in a lot of set-theory articles that also use TS terms "union" and "intersection".

But! Also! Before anybody mashes that "Close as Duplicate" button, I'd like to point out that I'm trying to solve a use case -- strongly typed indexing on a "normal" class -- not to advocate one specific solution. While negated types would almost certainly solve this, I'd like to leave this as a separate issue to see if any other promising solutions can be proposed.

@RyanCavanaugh
Copy link
Member

The real original is #17867

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants