Home > Enterprise >  How correctly type nested function to avoid any
How correctly type nested function to avoid any

Time:11-16

I have function that help me get array of images with theirs nested paths as in title, value. But I have problems with typing, since still need to use any.

Is there any way to type my code properly to avoid any? You can edit any types in the code below as you like.

const testIcons = {
  large: {
    image_title1: 'some image 1',
    action: {
      image_title2: 'some image 2',
      light: {
        image_title3: 'some image 3',
      },
    },
  },
}

type BaseIconPath = {
  [key: string]: BaseIconPath | string
}

// TS doesn't happy here so I use any(
const getNestedIcons = (basePath: any, icon: string): any => {
  return Object.keys(basePath).map((nestedIcon) => {
    if (typeof basePath[nestedIcon] === 'object') {
      return getNestedIcons(basePath[nestedIcon], `${icon}.${nestedIcon}`)
    }
    return { title: `${icon}.${nestedIcon}`, value: `${icon}.${nestedIcon}` }
  })
}

const getIconsListFromUiKit = (iconSize: keyof typeof testIcons): any => {
  const basePath: BaseIconPath = testIcons[iconSize]

  return Object.keys(basePath)
    .map((icon) => {
      // in case of nested icons
      if (typeof basePath[icon] === 'object') {
        return getNestedIcons(basePath[icon], icon)
      }

      return { title: icon, value: icon }
    })
    .flat(Infinity)
}

getIconsListFromUiKit('large')

TS playground link

CodePudding user response:

The correct return type should be { title: string; value: string }[]. You should also use flatMap instead as it simplifies the code.

type NestedRecord<T> = { [key: string]: T | NestedRecord<T> };

const getNestedIcons = (basePath: NestedRecord<string>, icon: string): { title: string; value: string }[] => {
    return Object.keys(basePath).flatMap((nestedIcon) => {
        const value = basePath[nestedIcon];

        if (typeof value === "object") {
            return getNestedIcons(value, `${icon}.${nestedIcon}`);
        }

        return { title: `${icon}.${nestedIcon}`, value: `${icon}.${nestedIcon}` };
    });
};

const getIconsListFromUiKit = (iconSize: keyof typeof testIcons) => {
    const basePath: BaseIconPath = testIcons[iconSize];

    return Object.keys(basePath).flatMap((icon) => {
        const value = basePath[icon];

        if (typeof value === "object") {
            return getNestedIcons(value, icon);
        }

        return { title: icon, value: icon };
    });
};

Playground

  • Related