-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Should the literal number value types of const-asserted arrays' indices be inferred? #34589
Comments
Partial workaround for const days = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'] as const;
/** "Mo" | "Tu" */
type FirstTwoDays = (typeof days)[1 | 2]
/** 7 */
type DaysCount = typeof days.length;
type PopFront<ArrT extends readonly any[]> =
((...arr: ArrT) => void) extends ((_: any, ...tail: infer TailT) => void)?
TailT :
never
;
type PushFront<TailT extends readonly any[], HeadT> =
((head : HeadT, ...arr: TailT) => void) extends ((...arr: infer ArrT) => void)?
ArrT :
never
;
type IndexOf<
ArrT extends readonly any[],
ValueT extends ArrT[number],
IndexTHack extends readonly any[] = [],
ResultT extends number = never
> =
{
0: number,
1: ResultT,
2: IndexOf<
PopFront<ArrT>,
ValueT,
PushFront<IndexTHack, any>,
ResultT|(ValueT extends ArrT[0] ? IndexTHack["length"] : never)
>
}[
number extends ArrT["length"] ?
0 :
ArrT["length"] extends 0 ?
1 :
2
]
;
declare function indexOf<ArrT extends readonly any[], ValueT extends ArrT[number]>(
arr: ArrT,
value : ValueT
): IndexOf<ArrT, ValueT>;
//2
const tu = indexOf(days, 'Tu' as const)
//2|3
const tuWe = indexOf(days, 'We' as 'Tu' | 'We')
//0|5
const suFr = indexOf(days, 'Su' as 'Su'|'Fr') |
For "number keys", const days = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'] as const;
/** "Mo" | "Tu" */
type FirstTwoDays = (typeof days)[1 | 2]
/** 7 */
type DaysCount = typeof days.length;
type PopFront<ArrT extends readonly any[]> =
((...arr: ArrT) => void) extends ((_: any, ...tail: infer TailT) => void)?
TailT :
never
;
type PushFront<TailT extends readonly any[], HeadT> =
((head : HeadT, ...arr: TailT) => void) extends ((...arr: infer ArrT) => void)?
ArrT :
never
;
type NumberKeysOf<
ArrT extends readonly any[],
IndexTHack extends readonly any[] = [],
ResultT extends number=never
> =
{
0: number,
1: ResultT,
2: NumberKeysOf<
PopFront<ArrT>,
PushFront<IndexTHack, any>,
ResultT|IndexTHack["length"]
>
}[
number extends ArrT["length"] ?
0 :
ArrT["length"] extends 0 ?
1 :
2
]
;
//type k = 0 | 1 | 2 | 3 | 4 | 5 | 6
type k = NumberKeysOf<typeof days>; |
Damn. That was an astoundingly clever usage of spread function params as a vehicle for recursively building an array! Tried it out myself and it indeed works. Then I was reminded of a talk (i think) anders hejlsberg had where he mentioned TypeScript having some internal recursion limit, and I was able to confirm: for me, I guess even if it had worked, it would've been a masterly albeit roundabout way of achieving what I thought would be a lightweight inference task. As you can see I am not a TypeScript expert lol |
There are ways to work around the depth limit but those are a bit out of scope =x I agree it would be nice to get TS to just give us the number literal keys of a tuple without hackery. A nicer way to type The workarounds above are... Not great |
This one is kind of problematic and would need a bunch of special handling, or new type system primitives we currently don't have. Fundamentally, |
getting the literal number types for |
Search Terms
array tuple const assertion literal index number
Suggestion, Use Cases, and Examples
I would like to infer the index type of a
const
-asserted array to be that of its position in the array, rather than justnumber
(i.e. I want the literal number type). However, I can't seem to create a way to extract this into atype
, even though I know TypeScript is holding onto this information somewhere.For example, this code follows my intuition:
Yet here,
index
is of typenumber
. Although this is understandable, given the signature ofArray['forEach']
, it begs the question - how could I assert, as theas const
does, thatindex
should be of type0 | 1 | 2 | 3 | 4 | 5 | 6
?Likewise, how could I get this to "work"?
The closest I can get to achieving my desired
type
is withbut it's not perfect:
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: