在 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. 用开头的 null 填充 Tuple 并记录最后推入的值时,我的方法是使用一个长度为 Start 的 TempTuple,并随着 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];
}
操场
