javascript - 如何在 typescript 中提供自动代码完成的同时将数组减少为对象?

标签 javascript typescript

最近我正在尝试 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);

.reducenot 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/

相关文章:

javascript - 在 Chrome 开发工具中隐藏 JavaScript 文件

javascript - 如何为 material-ui 组件正确使用 typescript 模块扩充?

javascript - 使用 JS 在两个 HTML 元素之间切换

javascript - 当我输入更多文本时,如何让工具提示背景扩展或增长?

javascript - Vue.js - 无法将日期/时间选择器添加到 vue.js 渲染的 html 元素中

javascript - 为什么自动高度不适用于图像?

angular - 如何捕获 Angular 2 中的内联模板错误?

javascript - 如何将 Java 正则表达式转换为 JS 正则表达式?

javascript - 未处理的 JS 异常 : Requiring unknown module "9"

ReturnType 帮助器中的 Typescript 类型推断