-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
feature: ability to extract union of valid index numbers for tuple #32917
Comments
For the time being, you can see a workaround in the S.O. issue I liked to above type ArrayKeys = keyof any[];
type StringIndices<T> = Exclude<keyof T, ArrayKeys>;
interface IndexMap {
"0": 0,
"1": 1,
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9,
"10": 10,
"11": 11,
"12": 12,
}
type CastToNumber<T> = T extends keyof IndexMap ? IndexMap[T] : number;
type Indices<T> = CastToNumber<StringIndices<T>>;
class FormArray<T extends [any, ...any[]]> {
constructor(public value: T) {}
get<I extends Indices<T>>(index: I): T[I] {
return this.value[index];
}
} |
EDIT: Disregard all this voodoo, easier solution below... |
I'm not on my computer but what about I think it should work. Can't test it at the moment, though |
Damn! Never thought of this... 👀 But that includes one union item too much.
type Drop1<T extends any[]> = ((...args: T) => void) extends ((a1: any, ...rest: infer R) => void) ? R : never; |
At least provide the |
@AlCalzone Do you need |
So having just tested, I find So this errors (playground link): type Indices<T extends {length: number}> = Exclude<Partial<T>["length"], T['length']>;
class FormArray<T extends [any, ...any[]]> {
constructor(public value: T) {}
// Here, `T[I]` errors because `I` is not a `keyof T`
get<I extends Indices<T>>(index: I): T[I] {
return this.value[index];
}
} In at least my case, @dragomirtitian's solution (which I repurposed above) is probably the best solution for the time being. This all being said, I don't understand why |
@thefliik Ashamed I did not think of it 😞 |
Interesting. I guess I've never used an optional property in a tuple. Optionals are so often equivalent to The reality is more useful. Still unless there is some way of getting the compiler to realize that |
I think the Partial made the length field itself optional, which then introduces an type Indices<T extends {length: number}> = Exclude<Partial<T>["length"], T['length']> & number;
class FormArray<T extends [any, ...any[]]> {
constructor(public value: T) {}
// It works now!
get<I extends Indices<T>>(index: I): T[I] {
return this.value[index];
}
} I'm still quite a TS newbie though, so my reasoning might not be based on how it actually workd... |
Search Terms
indexof array indexof tuple restrict argument to tuple index
Suggestion
I'd like the ability to restrict a type to a valid index number of a tuple. For example, given the tuple
[string]
, I'd like to extract the type0
. Given the tuple[string, number, object]
, I'd like to extract the type0 | 1 | 2
.Use Cases
see related S.O. question
Currently, if a generic class receives a type argument which is a tuple, it isn't possible to create a method on the class which restricts its argument to a valid index of that tuple.
Examples
Implementation ideas
I imagine there are several routes to achieving my goal.
Idea 1 (perhaps heavy handed):
Add a new keyword, such as
indexof
which can only be used on arrays and tuples. If indexof is used on an array, it will always returnnumber
. If indexof is used on a tuple, it returns a union of0 .... tuple length - 1
(e.g. if the tuple was of length 3indexof
would return0 | 1 | 2
).Idea 2:
Ability to cast a string type to the equivalent number type. For example, the ability to cast type
"0"
to0
. This would allow using thekeyof
keyword to get all properties of a tuple, cast property types to numbers (if possible), and then filter out any property types which aren't numbers (i.e. filter out"length"
,"splice"
, etc. and leave0 | 1 | 2
).For example, as pointed out in this comment, it is currently possible to get the indexes of a tuple in string form (i.e.
"0" | "1" | "2"
).Idea 3:
As pointed out in a comment, you can get the index numbers of a tuple using the following type:
Unfortunately, the result of this type is not considered a
keyof
the input tuple (which results in a type error if you try and use the type as a key for the tuple). If there were some way of using a type assertion to tell the compiler that this is, in fact, akeyof T
, that might also work.note: this type differs from the type presented in idea 2 (above) because, unlike this type, the type in idea 2 is a
keyof T
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: