AMendis
AMendis

Reputation: 1574

Typescript access object key dynamically

I have Theme.ts file like below

export default {
  COLORS: {
    DEFAULT: '#172B4D',
    PRIMARY: '#5E72E4',
    SECONDARY: '#F7FAFC',
  }
};

In my button component I import above theme file like this --> import argonTheme from "../constants/Theme";

In my button component I want to get access to that color dynamically like this

 const { small, shadowless, children, color, style, fontSize } = props;
 const colorStyle = color && argonTheme.COLORS[color.toUpperCase()];

This line gives me typescript error --> const colorStyle = color && argonTheme.COLORS[color.toUpperCase()];

This is the error I'm getting

Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{ DEFAULT: string; PRIMARY: string; SECONDARY: string ...

How can I write this line in typescript ?

const colorStyle = color && argonTheme.COLORS[color.toUpperCase()];

Upvotes: 3

Views: 2096

Answers (3)

enapupe
enapupe

Reputation: 17019

I believe the best option is to have an enum matching the properties of that object you have, declaring keys as string is a loose solution that might allow you have a key that does not exist.

enum ColorOptions {
  DEFAULT = 'DEFAULT',
  PRIMARY = 'PRIMARY',
  SECONDARY = 'SECONDARY',
}

Than you can safely do it like

const colorStyle = color && COLORS[ColorOptions.SECONDARY];

full code:

const COLORS = {
  DEFAULT: '#172B4D',
  PRIMARY: '#5E72E4',
  SECONDARY: '#F7FAFC',
}

enum ColorOptions {
  DEFAULT = 'DEFAULT',
  PRIMARY = 'PRIMARY',
  SECONDARY = 'SECONDARY',
}
const color = ColorOptions.PRIMARY;
const colorStyle = color && COLORS[color];
console.log(colorStyle);

or even consider killing the COLOR object and have just an enum

export enum COLORS {
  DEFAULT = '#172B4D',
  PRIMARY = '#5E72E4',
  SECONDARY = '#F7FAFC',
}
console.log(colorStyle); // #5E72E4

or if your code is already validating color input and you just want to touch that line and shut TS you could:

const colorStyle = color && argonTheme.COLORS[color.toUpperCase() as keyof typeof COLORS]; 

Upvotes: 1

Bourbia Brahim
Bourbia Brahim

Reputation: 14702

Set a type for you for your COLORS , otherwise the any type would be set by default:

in your case its stringkey with string value , thus should look like

export default {
    const COLORS :{ [key: string]: string } =  {
      DEFAULT: '#172B4D',
      PRIMARY: '#5E72E4',
      SECONDARY: '#F7FAFC',
    }
};

Upvotes: 0

Titulum
Titulum

Reputation: 11446

You have to provide a type for the COLORS object:

// Theme.ts
const COLORS: Record<string, string> =  {
  DEFAULT: '#172B4D',
  PRIMARY: '#5E72E4',
  SECONDARY: '#F7FAFC',
}

export default { COLORS };

// Other Component:
const color= 'PRIMARY';
const colorStyle = color && COLORS[color.toUpperCase()];

A working example here.

Upvotes: 2

Related Questions