最近我正在尝试 typescript ,但在深入研究它的过程中,我被困在一个无法前进的地方。所以我有一个字符串数组,我想将它缩减为一个对象,同时获得所有正确的提示和代码完成。虽然我已经到达了 typescript 没有抛出任何错误的地方,但我仍然无法实现代码完成行为。在此粘贴示例代码以供引用。
interface GetObjI {
[key: string]: string;
}
function getObj(myArray: string[]): GetObjI {
return myArray.reduce((prev, curr) => {
prev[curr] = curr;
return prev;
}, {});
}
const arr = ["name", "age"];
const obj = getObj(arr);
console.log(obj.age); // Here I wasn't able to achieve code completion.
最佳答案
使用严格的 TypeScript 设置,您的代码应该会抛出错误。
prev[curr] = curr;
抛出
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.
No index signature with a parameter of type 'string' was found on type '{}'.(7053)
这是有道理的 - 当您传入累加器时,您没有为累加器提供任何特殊类型,因此分配给它的属性不会与其现有类型(作为空对象)相匹配。
使用通用类型参数来指示累加器的类型,并将 getObj
也设为通用类型,以便可以传递 myArray
中的值(而不是仅使用 string[]
,后者过于通用)。
您还需要键入在 as const
中传递的数组,这样它就不会在函数调用之前扩大到 string[]
。
function getObj<T extends readonly string[]>(myArray: T) {
// Type out the type of the full object with all properties here to be DRY
type Accum = Record<T[number], T[number]>;
// The object doesn't have all properties inside the callback, though
// so we need to use Partial to indicate that some or all can be missing
return myArray.reduce<Partial<Accum>>((prev, curr: T[number]) => {
prev[curr] = curr;
return prev;
}, {}) as Accum; // When returning, indicate that it's no longer Partial, but has all properties
}
const arr = ["name", "age"] as const;
const obj = getObj(arr);
console.log(obj.age);
但 .reduce
是 not the right tool for this situation - 它需要冗长的 TypeScript 键入,即使在标准 JavaScript 中也不是一个好主意,因为累加器仍然是同一个对象。只需使用循环即可。
function getObj<T extends readonly string[]>(myArray: T) {
const obj: Record<string, string> = {};
for (const prop of myArray) {
obj[prop] = prop;
}
return obj as Record<T[number], T[number]>;
}
或者使用 Object.fromEntries
const getObj = <T extends readonly string[]>(myArray: T) =>
Object.fromEntries(myArray.map(prop => [prop, prop])) as Record<T[number], T[number]>;
不幸的是,所有这些方法都需要帮助 TS 以及一些类型断言。使用循环或 reduce
需要在循环内将属性键入为可选,但在循环外需要 - 并且 Object.fromEntries
仅给出 Record<string, T>
类型作为响应,这不够具体。
关于javascript - 如何在 typescript 中提供自动代码完成的同时将数组减少为对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71540263/