3

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()];
3
  • 2
    Not related but I'd export const COLOR instead of an unnamed default object Commented Jan 25, 2021 at 10:50
  • Could you add the typings for your props. TS is complaining that color is implicitely (not even explicitely) typed as any Commented Jan 25, 2021 at 10:56
  • An alternative solution is to use as keyof typeof like so: argonTheme.COLORS[color.toUpperCase() as keyof typeof argonTheme.COLORS]. Not encouraged, but probably good to know. Commented Jan 26, 2021 at 6:29

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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]; 

Comments

0

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',
    }
};

4 Comments

Why provide duplicate answers?
@Titulum , could you explain where is the duplication here !!
We both tell the questioner to type the COLORS object. Our answers are nearly identical, the only difference is how the COLORS object is typed. But Record<string, string> and { [key: string]: string} are both identical types, the only difference is that one is more verbose.
That the context of the answer hence the similarity , but not a duplication ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.