Υπάρχει τρόπος να δηλώσετε μια διαδοχική ένωση λεκτικών συμβολοσειρών στο Typescript
Θέλω να δηλώσω έναν τύπο ένωσης κυριολεκτικών συμβολοσειρών: "10" | "11" | ... | "99".
Σκέφτηκα μια λύση για να παρακάμψω το πρόβλημα, αλλά δεν δούλεψε
const arr = Array.from({
length: 90
}, (_, i) => i + 10) as const; // expected arr type is readonly [10, 11, ..., 99]
// If above works, then
type NumberToString<T extends number> = `${T}`;
type Successive = NumberToString<typeof arr[number]>;
Αναρωτιέμαι αν υπάρχει τρόπος να ορίσω γρήγορα το "10" έως "99" πάνω από το επίπεδο τύπου;
Απάντηση #1
Αυτό θα πρέπει να είναι δυνατό στην επόμενη έκδοση (4.5) του TypeScript όπου το όριο βάθους δημιουργίας τύπων θα πρέπει να αυξηθεί
type _NextValue<From, LastValue, R extends any[]> = LastValue extends number
? R['length']
: R['length'] extends From ? From : null
/**
* Fill array with `null` placeholders until index `From`
* Then append array length as a member until getting to `To` length
* Example: `_Values<5, 11>` will result in `[null, null, null, null, null, 5, 6, 7, 8, 9, 10]`
*/
type _Values<From, To, R extends any[] = [], LastValue = null> = R['length'] extends To ? R :
_Values<
From,
To,
[...R, _NextValue<From, LastValue, R>],
_NextValue<From, LastValue, R>
>
/**
* Exclude nulls and convert to strings
*/
type NumbersToStrings<T extends Array<number | null>> = `${NonNullable<T[number]>}`;
type N10_99 = NumbersToStrings<_Values<10, 100>> // "10" | "11" | "12" | "13" | "14" | "15" | ... | "99"
Παιδική χαρά
Απάντηση #2
Βρήκα μια διαφορετική προσέγγιση για να λύσω αυτή την ερώτηση, ενώ ο @Aleksey L. γεμίζει το Tuple με αρχικά null και καταγράφει την τελευταία ανασυρόμενη τιμή, η δική μου προσέγγιση είναι να χρησιμοποιήσω ένα TempTuple του οποίου το μήκος είναι Start και μεγαλώνει καθώς μεγαλώνει το ResTuple.
type AddOne<T extends number, Tuple extends unknown[] = []> =
Tuple["length"] extends T ? [1, ...Tuple]["length"] :
AddOne<T, [1, ...Tuple]>;
/** fill tuple to a fixed length */
type FillTuple<T extends number, Tuple extends unknown[] = []> =
Tuple["length"] extends T ? Tuple :
FillTuple<T, [1, ...Tuple]>;
/** TempTuple is meant to grow as ResTuple grow */
type RangeTuple<Start extends number, End extends number, ResTuple extends unknown[] = [], TempTuple extends unknown[] = FillTuple<Start>> =
TempTuple["length"] extends AddOne<End> ? ResTuple :
RangeTuple<Start, End, [...ResTuple, `${TempTuple["length"]}`], [1, ...TempTuple]>;
{
type _ = RangeTuple<10, 99>[number];
}
παιδική χαρά
