将 Array.prototype.includes() 替换为不 return 布尔值的方法

Replace Array.prototype.includes() with a method that does not return a boolean

我在 Typescript 中有一个函数,其中,从字符串中,它 return 是包含该变量的对象的键。

我正在使用 Array.prototype.includes() 检查变量是否存在,这可以 return truefalse,因此将结果变量键入 [=17] =] 给我打字错误。

这是错误:

Type 'unknown' cannot be assigned to type 'string'

这是我的功能:

let testData = {
  data1: ['CAR','PLANE'],
  data2: ['COUNTRY','CITY']
};

let asset = 'car';

function resKey(asset) {

  let res = Object.keys(testData).find(key => {
    const value = testData[key]
  
    return value.includes(asset.toUpperCase())
  })

  return res

}

console.log(resKey(asset));

我只会将对象中的值传递给它,因此我不需要检查它是否存在。

我的问题:我如何修改函数,使其只 return 键而不需要检查它是否存在?

正如我在评论中指出的那样,您可以通过为当前函数提供一些类型注释来使其对 Typescript 友好。

或者,您可以通过创建 testDataMap 并直接通过 value 检索 key 来避免 find()。请记住,如果不同资产数组之间存在重复值,这将 return 最后一个实例的键(与 find() 将 return 第一个实例的键相反)。

let testData = {
  data1: ['CAR', 'PLANE'],
  data2: ['COUNTRY', 'CITY']
};

let asset = 'car';

function resKey(asset) {
  const resMap = new Map(Object.entries(testData).flatMap(([k, v]) => v.map(a => [a, k])));
  
  return resMap.get(asset.toUpperCase());
}

console.log(resKey(asset));

为避免在每次调用函数时都创建一个新的 Map,您可以使用一点柯里化。

function resKeyFactory(data) {
  const resMap = new Map(
    Object.entries(data)
      .flatMap(([k, v]) => v.map(a => [a, k]))
  );

  return (asset) => resMap.get(asset.toUpperCase());
}

const
  testData = {
    data1: ['CAR', 'PLANE'],
    data2: ['COUNTRY', 'CITY']
  },
  asset = 'car',
  resKeyTestData = resKeyFactory(testData);

console.log(resKeyTestData(asset));
console.log(resKeyTestData('city'));

Typescript 需要足够高的目标才能接受 flatMap playground.

您可以使用 Object.entries()find()

let testData = {
  data1: ['CAR', 'PLANE'],
  data2: ['COUNTRY', 'CITY']
};

function resKey(data, asset) {
  return Object.entries(data).find(([_, v]) => {
    return v.includes(asset.toUpperCase())
  })?.[0] || "no key found";
}

console.log(resKey(testData, "car"));
console.log(resKey(testData, "something"));
console.log(resKey(testData, "city"));

如果你想打字,它看起来像这样。

interface IData {
  data1: string[];
  data2: string[];
}

let testData: IData = {
  data1: ['CAR', 'PLANE'],
  data2: ['COUNTRY', 'CITY']
};

function resKey(data: IData, asset: string): string {
  return Object.entries(data).find(([_, v]) => {
    return v.includes(asset.toUpperCase())
  })?.[0] || "no key found";
}