如何将只读字符串[]泛型转换为已知对象



我正在尝试将通用readonly string[]转换为具有已知键的对象。但我遇到了错误:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record<T[number], number>'.
No index signature with a parameter of type 'string' was found on type 'Record<T[number], number>'.

代码:

class ArrayToObject<T extends readonly string[]> {
constructor (private keys : T) {}
GET_OBJECT () {
const all = {} as Record<T[number], number>
for (const index in this.keys) {
all[this.keys[index]] = index
}
return all;
}
}

我基本上想要的是类似于以下的东西:

const a = ["a", "b"] as const
const o : Record<typeof a[number], number> = {
a : 1,
b : 2
}

操场

这是因为类型系统只能知道T extends readonly string[],但无法正确推断其元素的类型。将T定义为元素类型可以帮助类型系统推断它

此外,for...in语句将产生一个字符串键值。您需要将其转换为数字,或者使用Array.keys()Array.entries()来获得数字索引。

class ArrayToObject<T extends string> {
constructor (private keys : readonly T[]) {}
GET_OBJECT () {
const all = {} as Record<T, number>
for (const [index, value] of this.keys.entries()) {
all[value] = index // + 1 if you want 1-based
}
return all;
}
}

操场

您可以使用类型推断从只读字符串中获取字符串并集,如下所示:

const a = ["a", "b"] as const;
type StringFromReadonlyArray<T extends readonly string[]> = T extends readonly (infer U)[] ? U : string;
const tooMany: Record<StringFromReadonlyArray<typeof a>, number> = {
a: 1,
b: 2,
c: 3, // <-- Error: Type '{ a: number; b: number; c: number; }' is not assignable to type 'Record<"a" | "b", number>'.
};
const notEnough: Record<StringFromReadonlyArray<typeof a>, number> = { // <-- Error: Property 'b' is missing in type '{ a: number; }' but required in type 'Record<"a" | "b", number>'.
a: 1,
};
const justRight: Record<StringFromReadonlyArray<typeof a>, number> = {
a: 1,
b: 2,
};

TypeScript游乐场

如果可能的话,StringFromReadonlyArray实用程序类型会从只读数组中提取字符串并集,否则它将解析为通用string类型。

最新更新