Typescript 获取数组文本的索引类型
假设我有以下数组文字:Typescript 获取数组文本的索引类型,typescript,Typescript,假设我有以下数组文字: const list = ['foo', 'bar', 'baz'] as const; 我试图生成一个类型,它表示这个数组的可能索引。我试图实现以下目标: const list = ['foo', 'bar', 'baz'] as const; type ListIndex = Exclude<keyof (typeof list), keyof []>; const list=['foo','bar','baz']作为const; 类型ListInd
const list = ['foo', 'bar', 'baz'] as const;
我试图生成一个类型,它表示这个数组的可能索引。我试图实现以下目标:
const list = ['foo', 'bar', 'baz'] as const;
type ListIndex = Exclude<keyof (typeof list), keyof []>;
const list=['foo','bar','baz']作为const;
类型ListIndex=排除;
但是ListIndex
现在变成了“0”|“1”|“2”
,而不是0 | 1 | 2
谁能告诉我如何获得所需的0 | 1 | 2
类型吗?您得到的是。但我们可以通过一些映射技巧来实现您所需要的:
const list = ['foo', 'bar', 'baz'] as const;
type StrNum = {
"0": 0,
"1": 1,
"2": 2,
"3": 3,
"4": 4 // if your tuple will be longer extend this for it
}
type MapToNum<A extends keyof StrNum> = {
[K in A]: StrNum[K]
}[A] // this maps string keys into number by using StrNum type
type ListIndex = MapToNum<Exclude<keyof (typeof list), keyof []>>;
// result type 0 | 1 | 2
const list=['foo','bar','baz']作为const;
类型StrNum={
"0": 0,
"1": 1,
"2": 2,
"3": 3,
“4”:4//如果您的元组将更长,请为此扩展此元组
}
类型MapToNum={
[K in A]:StrNum[K]
}[A] //使用StrNum类型将字符串键映射为数字
类型ListIndex=MapToNum;
//结果类型0 | 1 | 2
没有一种内置的方法来实现这一点,这非常烦人。我们正在寻找解决这一问题的方法,但目前我们必须解决这一问题
这就是我在自己的项目中所做的:
/** Type of the elements in an array */
type ElementOf<T> = T extends (infer E)[] ? E : T extends readonly (infer E)[] ? E : never;
/** Used internally for `Tail`. */
type AsFunctionWithArgsOf<T extends unknown[] | readonly unknown[]> = (...args: T) => any;
/** Used internally for `Tail` */
type TailArgs<T> = T extends (x: any, ...args: infer T) => any ? T : never;
/** Elements of an array after the first. */
type Tail<T extends unknown[] | readonly unknown[]> = TailArgs<AsFunctionWithArgsOf<T>>;
/** Used internally for `IndicesOf`; probably useless outside of that. */
type AsDescendingLengths<T extends unknown[] | readonly unknown[]> =
[] extends T ? [0] :
[ElementOf<ElementOf<AsDescendingLengths<Tail<T>>[]>>, T['length']];
/** Union of numerical literals corresponding to a tuple's possible indices */
type IndicesOf<T extends unknown[] | readonly unknown[]> =
number extends T['length'] ? number :
[] extends T ? never :
ElementOf<AsDescendingLengths<Tail<T>>>;
您可以使用以下类型:
type Indices<T extends readonly any[]> = Exclude<Partial<T>["length"], T["length"]>
这是有意的,而且是书面设计的。这回答了你的问题吗?所有这些都是为了在索引数组时进行类型检查,这样就不会爆炸吗?我想进一步了解这个问题的背景。
list
是否始终定义为索引类型正上方的常数?为什么不使用字符串枚举?@DexterW当前用例是react组件的类型化属性。组件可以接收一个prop,该prop应该是在主题中某处定义的数组的现有索引(例如propmarginTop={3}
,其中主题中的数组是{margins:[0,4,8,16,…])
@KamNadimi感谢这些链接。它没有回答我的问题,但提供了更多的见解。感谢你详尽的回答,但我担心这对我来说是太深入了一步:-)答案可能就在我面前,但是你能用创建实际的数字联合类型的例子更新你的答案吗?数组文本作为输入;对不起,不清楚。它只是类型ListIndex=indicatesof
。我会把它添加到答案中。谢谢你的回答,如果没有其他更合适的解决方案,它看起来就像一个不错的逃生舱:-)
interface Array<T> {
/**
* Returns the index of the first occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search.
* If `fromIndex` is omitted, the search starts at index 0.
* Returns -1 if `searchElement` is not found.
*/
indexOf<This extends T[], T>(this: This, searchElement: T, fromIndex?: IndicesOf<This>): -1 | IndicesOf<This>;
}
interface ReadonlyArray<T> {
/**
* Returns the index of the first occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search.
* If `fromIndex` is omitted, the search starts at index 0.
* Returns -1 if `searchElement` is not found.
*/
indexOf<This extends readonly T[], T>(this: This, searchElement: T, fromIndex?: IndicesOf<This>): -1 | IndicesOf<This>;
}
type Indices<T extends readonly any[]> = Exclude<Partial<T>["length"], T["length"]>
type Test = Indices<typeof list> // Test = 0 | 1 | 2 // works!