zhuber
zhuber

Reputation: 5524

Resolve generic property name

I'm trying to create object with generic property name

type ColorStyle<T extends string> = Record<ColorType, Record<T, string>>;

function getColorStyle<T extends string>(propertyName: T): ColorStyle<T> {
  return {
    accent: { [propertyName]: colors.accent },
    primary: { [propertyName]: colors.primary },
    secondary: { [propertyName]: colors.secondary },
    tertiary: { [propertyName]: colors.tertiary },
    black: { [propertyName]: colors.black },
    white: { [propertyName]: colors.white },
    gray: { [propertyName]: colors.gray },
    gray2: { [propertyName]: colors.gray2 },
  }
}

Error I'm getting is

Type '{ [x: string]: string; }' is not assignable to type 'Record<T, string>

I wanted to use it us such:

const colorStyle = getColorStyle('color');
const primaryColor = colorStyle.primary.color;

const backgroundColorStyle = getColorStyle('backgroundColor');
const primaryBackgroundColor = backgroundColorStyle.primary.backgroundColor;

EDIT:

export const colors = {
  accent: "#F3534A",
  primary: "#0AC4BA",
  secondary: "#2BDA8E",
  tertiary: "#FFE358",
  black: "#323643",
  white: "#FFFFFF",
  gray: "#9DA3B4",
  gray2: "#C5CCD6"
};

export type ColorType = keyof typeof colors;

Upvotes: 0

Views: 78

Answers (1)

tmhao2005
tmhao2005

Reputation: 17474

I think the problem is from the way Typescript infers your body { [propertyName]: colors.accent } to { [x: string]: string } which is different from { [P in string]: string } (Record<string, string>). But it allows you to cast { [propertyName]: colors.accent } as Record<T, string> which means you can just simply cast your result as your return value:

Cast single item:

return {
  accent: { [propertyName]: colors.accent } as Record<T, string>,
  // ...
}

Or you can cast entire object:

return {
  accent: { [propertyName]: colors.accent },
  // ...
} as ColorStyle<T>

Upvotes: 2

Related Questions