typescript 将数组类型减少为特定类型?类型为{{“a ",'b"]的{"a",' b "]而不是string[]

v8wbuo2f  于 2023-10-22  发布在  TypeScript
关注(0)|答案(1)|浏览(109)

我有一个字符串数组,我需要将其简化为具有特定值的数组类型也就是说,string[]类型的“a "," b”]必须是“a”,“b”]类型当然,您可以手动将“a "," b”]写成“a ",”b"]”,但这不是很方便

export function myFunction<T extends string[]>(
  required: T
): Record<T[number], any> {}

我需要这个函数返回一个对象,它包含“required”数组中包含的条目,所以如果我调用myFunction,('a ','b','c ']),编译器和IDE应该知道返回的对象只包含a,b和c键现在当我像myFunction一样调用它时它可以工作('a ','b','c '] as 'a','b ','c']),但我不想显式指定类型如何自动转换“required”变量的类型?

tjvv9vkg

tjvv9vkg1#

通常,像["a", "b", "c"]这样的数组字面量被推断为具有string[]类型。但是如果数组文字在所谓的“const上下文中”,它将被推断为文字类型的readonly元组:readonly ["a", "b", "c"] .这是接近你想要的:你没有要求readonly,但是除非你打算修改数组,否则它不应该有太大的关系,当每个元素的类型是一个已知的文字字符串值时,修改数组的内容没有多大意义。我就当你不在乎了。
获取const上下文的一种方法是让编写数组文字的人使用constAssert:

const a = ["a", "b", "c"] as const;
// const a: readonly ["a", "b", "c"]
const p = myFunction(a);
// const p: Record<"a" | "b" | "c", any>

但如果数组文字直接作为myFunction()的参数给出,则还可以通过为T指定const类型参数修饰符来指定const上下文:

declare function myFunction<const T extends readonly string[]>(
  required: T
): Record<T[number], any>;

const o = myFunction(["a", "b", "c"]);
// const o: Record<"a" | "b" | "c", any>

请注意,为了支持readonly元组,我必须将类型参数约束从string[]更改为readonly string[]。否则,推断将失败,因为readonly ["a", "b", "c"]不能分配给string[]。同样,我假设您不关心这一点,除非有一些重要的用例中断。
重要的是要记住,如果数组字面量的类型被推断为string[],则关于元素顺序和字面量类型的更具体的信息将被丢弃并且无法检索。您必须以某种方式直接将数组文字放在const上下文中。你不能在事后加一个:

const oops = ["a", "b", "c"]; // forgot "as const" here
// const oops: string[]

const q = myFunction(oops);
// const q: Record<string, any>

q的类型是Record<string, any>,因为oops的类型是string[]myFunction中的const修饰符不能撤销这一点,因此q的类型为Record<string, any>
Playground链接到代码

相关问题