typescript 如何使用Object.keys()键入嵌套对象?

yhuiod9q  于 2022-12-14  发布在  TypeScript
关注(0)|答案(2)|浏览(189)

我正在使用嵌套对象,并尝试使用Object.keys()和forEach()获取属性。问题是当我想获取嵌套键filteringState[item][el]时。
如何键入这样的函数?

interface InitialStateTypes {
    country: {
        "italy": boolean,
    },
    board: {
        "full": boolean,
    },
    transport: {
        "bus": boolean,
        "own": boolean
    },
}

interface FilteringDataTypes {
    country: string[],
    board: string[],
    transport: string[],
}

const collectFilteringData = (filteringState: InitialStateTypes) => {
    let filteringData = <FilteringDataTypes>{};

    Object.keys(filteringState).forEach((item) => {
        Object.keys(filteringState[item]).forEach((el) => {
            if (filteringState[item][el]) {
                if (!filteringData[item]) {
                    filteringData[item] = [el];
                } else {
                    filteringData[item] = [...filteringData[item], el];
                }
            }
        });
    });
    return filteringData;
};

export default collectFilteringData;
pvabu6sv

pvabu6sv1#

当使用keys方法时,可能会有点混乱,因为它只期望输出字符串。(这不是不合理的,因为JS对象键被认为是字符串,当然TypeScript更担心这一点)
下面是一种可能的方法:

interface InitialStateTypes {
  country: {
      "italy": boolean,
  },
  board: {
      "full": boolean,
  },
  transport: {
      "bus": boolean,
      "own": boolean
  },
}

interface FilteringDataTypes {
  country: string[],
  board: string[],
  transport: string[],
}

const collectFilteringData = (filteringState: InitialStateTypes):FilteringDataTypes => {
  let filteringData = {} as FilteringDataTypes

  (Object.keys(filteringState) as Array<keyof InitialStateTypes>).forEach((item) => {
      (Object.keys(filteringState[item]) as Array<keyof InitialStateTypes[typeof item]>).forEach((el) => {
          if (filteringState[item][el]) {
              if (!filteringData[item]) {
                  filteringData[item] = [el];
              } else {
                  filteringData[item] = [...filteringData[item], el];
              }
          }
      });
  });
  return filteringData;
};

export default collectFilteringData
  • 在这里,类型Assert的作用是告诉TypeScript您实际期望的类型。
  • 然后允许将正确的类型传递给forEach方法
  • 棘手的是,它是嵌套的,因此您必须执行另一个类型Assert,您还需要从第一个forEach传入typeof item的值

格式化(使用Prettier)后,它最终看起来如下所示:

const collectFilteringData = (
  filteringState: InitialStateTypes
): FilteringDataTypes => {
  let filteringData = {} as FilteringDataTypes;

  (Object.keys(filteringState) as Array<keyof InitialStateTypes>).forEach(
    (item) => {
      (
        Object.keys(filteringState[item]) as Array<
          keyof InitialStateTypes[typeof item]
        >
      ).forEach((el) => {
        if (filteringState[item][el]) {
          if (!filteringData[item]) {
            filteringData[item] = [el];
          } else {
            filteringData[item] = [...filteringData[item], el];
          }
        }
      });
    }
  );
  return filteringData;
};

注意
我已经在TypeScript 4.6.2中写出了这个答案,keys方法的类型如下:

keys(o: object): string[];
tkclm6bt

tkclm6bt2#

您可以使用keyof运算子。
示例:

type Point = { x: number; y: number };
type P = keyof Point;

以下是更多详细信息:https://www.typescriptlang.org/docs/handbook/2/keyof-types.html
巢状数据:

type Point = { test: {x: number; y: number} };
type P = keyof Point["test"];

相关问题