【问题标题】:How can I type this function without resorting to 'any'如何在不使用“任何”的情况下键入此功能
【发布时间】:2019-08-03 09:32:04
【问题描述】:

我有这个函数,它接受一个对象和两个字符串,并返回一个类型化对象数组,使用字符串从提供的对象中选择两个属性。

我的编译器警告 元素隐含地具有“任何”类型,因为类型“{}”没有索引签名。映射函数内的两行。

export interface SelectOption {
  value: string;
  label: string;
}

/**
 * Map an array of objects to an array of objects compatible with select drop downs
 * specifying the keys to be used for the value and the label
 * @param items the object to map from
 * @param valueField The field in the object containing the value
 * @param labelField The field in the object containing the label
 */
export const mapObjectsToSelectOptions = (
  items: object[],
  valueField: string,
  labelField: string,
): SelectOption[] => {
  return items
    .map(o => ({
      value: o[valueField],
      label: o[labelField],
    }));
};

Typescript 有什么办法解决这个问题吗?我尝试为 items 参数创建一个类型,如下所示:

interface ObjectBase {
  [key: string]: string;
}

当然,提供的对象可能没有这样的类型,所以在调用函数时会出错。我可以以某种方式使用泛型吗?

【问题讨论】:

  • 尝试使用keyof类型:valueField: keyof ItemTypeHere

标签: typescript


【解决方案1】:

您需要将mapObjectsToSelectOptions 设为通用,具有3 个类型参数:一个用于确切的对象类型T,另外两个用于两个字段名称:用于值和用于标签,分别命名为VFLF。那么编译器就可以推断出值类型为T[VF],标签类型为T[LF]

export const mapObjectsToSelectOptions = 
<T extends object, VF extends keyof T, LF extends keyof T>(
  items: T[],
  valueField: VF,
  labelField: LF,
) => { // the inferred return type is OK: {value: T[VF], label: T[LF]}[]
  return items
    .map(o => ({
      value: o[valueField],
      label: o[labelField],
    }));
};

const testObject1 = {
    a: 1,
    b: 'B',
    c: 'Q'
}

const testObject2 = {
    a: 5,
    b: 'B',
    e: 'E'
}

const selectOptions = mapObjectsToSelectOptions([testObject1, testObject2], 'a', 'b');
// returned type is
// const selectOptions: {
//     value: number;
//     label: string;
// }[]

const selectOptions2 = mapObjectsToSelectOptions([testObject1, testObject2], 'a', 'c'); 
// error, not all objects have 'c'

【讨论】:

    最近更新 更多