3

I don't know if the question title was sugestive but my problem is, in a constructor I got a rest parameter that must be the keys of an object and I want that, when I call the constructor, it only allows the keys that isn't yet used.

I don't know if it's possible, but if it is, I would be glad if someone can help me whit it.

Some code to ilustrate my problem below:


class MyClass<GenType> {
    // With the Utility Type Partial<?> I achieved the behavior of allowing only the keys
    // that the object type GenType has, but it still allows that the same key can be passed
    // as argument more than once
    constructor(...rest: Array<Partial<keyof GenType>>) {

    // constructor stuff
    }

}

type MyGenericType = {
    key1: string,
    key2: number,
    key3: Array<number>
}

// Here, in the initialization, it allows to insert the same key multiple times, but
// i want it to allow that a key can be passed just once
const myClassObject = new MyClass<MyGenericType>("key1", "key2", "key1");

Bellow an image of the problem in my real code:

real code problem

Note that it allow to pass the same key more than once and the code sugestion show all the object keys, I want that it didn't allow the same key more than once and the code sugestion only shows the remaining keys

The effect that I want is possible? If yes, how could I achieve it?

Thanks!

  • This is not easily achievable with Typescript today. Though I think [this answer](https://stackoverflow.com/questions/57016728/is-there-a-way-to-define-type-for-array-with-unique-items-in-typescript) might get you close, it's got some crazy stuff there that is not for the faint of heart. Does that answer your question? – Alex Wayne Jun 23 '22 at 18:40
  • Note that `Partial` is almost certainly not what you want. `keyof GenType` is going to be something like a union of string literals, and `Partial` just makes object properties optional. It won't do anything to a string, and you wouldn't want it to because who even wants to think of a `string` that might not have a `length` or a `toUpperCase()` method – jcalz Jun 23 '22 at 18:43
  • [this solution](https://tsplay.dev/w2Pkbm) might work for you. It simply creates a union of all possible key combinations. For larger unions this will blow up performance-wise though since every combination needs to be calculated... – Tobias S. Jun 23 '22 at 18:51
  • How many keys does your real type have? If it's more than about 6 or 7 you'll run into big issues with the union-of-all-tuples approach. The other approach to this is to add a new generic type parameter for the key tuple and verify it, but then you'll run into issues with partial generic type inference and need currying or some such yuckiness. – jcalz Jun 23 '22 at 19:17
  • @jcalz it's about 6~7, or even more, it's not defined :c – Rafael Furtado Jun 23 '22 at 19:21
  • @TobiasS. it worked, but now i'm afraid of the issues with the performance :/ – Rafael Furtado Jun 23 '22 at 19:21
  • You could do [this](https://tsplay.dev/mbBadm) but it's ugly (and doesn't even work unless the compiler keeps track of the args as tuples. I'd say this isn't really something you want the compiler to do; I'd prefer a runtime check or a runtime sanitizer (e.g., just ignore duplicates). You could also make some kind of builder like [this](https://tsplay.dev/mAKgvw)? Does either of those meet your needs? If so I could write up an answer, otherwise what am I missing? – jcalz Jun 23 '22 at 19:41
  • I think it's becoming a way more too complex to achieve what i want and i gonna try another solution for my problem, but i really appreciate all the proposed solutions – Rafael Furtado Jun 23 '22 at 20:01

1 Answers1

-1

For everyone that is seeking for something similar, with the comments posted I assume that yes, it's possible to achieve it, but no, there is not easy or eficient way to do that, some of the possibilities are in the links bellow:

Possibility 1

Possibility 2

Thanks for all the comments trying to help and hopes that it helps others!

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • While this may answer the question, all of the relevant details in order to solve the problem are contained in links. The links are good to have, but your answer should be useful without them. In this case, include the code examples in your answer. – Jesse Jun 24 '22 at 22:33