我已经找到了解决方案,但我就是不明白为什么不添加一个返回类型来解决这个问题:

我有一个根据ID而不是数组来键入TypeORM实体的函数.

import { instanceToPlain } from 'class-transformer';

export default function keyBy(
  listOfObjects: object[],
  mappingKey: string,
): object // <--- i had to remove this 
{
  const data = listOfObjects.reduce((acc: any, currentVal: any) => {
    const tempObj = instanceToPlain(currentVal);

    if (tempObj[mappingKey] === undefined) {
      throw new Error(`Mapping key:${mappingKey} not found in the Array`);
    }
    acc[tempObj[mappingKey]] = currentVal;

    return acc;
  }, {});
  return data;
}

我必须删除对象返回类型,否则下面的代码行会给出错误.

const usersById = keyBy(users, 'id');
const user = usersById[message.senderId];

为了理解,我try 了几种方法,包括:

const user = usersById[Object.keys(usersById)[0] as keyof typeof usersById];

但后来我得到了:

Property 'firstName' does not exist on type 'never'.

无论如何,删除key By的返回类型可以解决这些错误,但我真的很想了解这里发生了什么.

推荐答案

简单的回答是:类型object不能用来打字.

类型object是原始的,每个对象都是它的子类型.但使用它输入变量与使用{}输入变量是相同的,因此不允许使用任何键

如果删除函数的返回类型,则TypeScrip会将其推断为any,因为您返回的是一个未类型化的动态对象.

如果希望函数返回动态对象,则可以使用泛型类型Record

Record<string, any> // will return a set of key value, where key is a `string` and value is of type `any`

但我建议你找到一种方法,根本不使用any.如果你知道你期待的是什么类型,也许你应该直接定义它.

如果返回类型取决于参数中的listOfObjects类型,或许可以使用泛型类型.

对于您的示例,我假设这样的操作应该有效:

export default function keyBy<T, K extends keyof T>(
  listOfObjects: T[],
  // Only allow key with a string value
  mappingKey: T[K] extends string ? K : never
): Record<string, T> {
   // Don't need to type `currentVal` anymore, and we type the return value of the `reduce` method
    const data = listOfObjects.reduce<Record<string, T>>((acc, currentVal) => {
    const tempObj = instanceToPlain(currentVal);
    
    if (tempObj[mappingKey] === undefined) {
      throw new Error(`Mapping key:${mappingKey} not found in the Array`);
    }
    // We tell typescript that `currentVal[mappingKey]` is a string so we can index `acc`
    acc[tempObj[mappingKey] as string] = currentVal;

    return acc;
  }, {});
  return data;
}

Typescript相关问答推荐

如何在TypScript中使参数类型化但可选

发出与HTML多姆事件重叠的Angular事件

具有条件通用props 的react 类型脚本组件错误地推断类型

在角形加载组件之前无法获取最新令牌

排序更改数组类型

如何根据参数的值缩小函数内的返回类型?

SortKey类型不起作用,尽管它使用的单个类型工作正常<>'

webpack错误:模块找不到.当使用我的其他库时,

如何在Typescript 中输入两个相互关联的变量?

PrimeNG日历需要找到覆盖默认Enter键行为的方法

APIslice-CreateAPI的RTK打字错误

Angular NgModel不更新Typescript

错误TS2403:后续变量声明必须具有相同的类型.变量';CRYPTO';的类型必须是';CRYPATO';,但这里的类型是';CRYPATO';

如何在处理数组时缩小几个派生类实例之间的类型范围?

Cypress页面对象模型模式.扩展Elements属性

如何实现异构数组内函数的类型缩小

常量类型参数回退类型

如何创建内部和外部组件都作为props 传入的包装器组件?

如何将对象的字符串文字属性用作同一对象中的键类型

Typescript泛型验证指定了keyof的所有键