1

This is the part of palette, i am using a IPalette interface right here:

{
  warningColor: '#FFCA28',
  smallWidgetBackground: ["rgba(255,255,255,0.15)", "rgba(255,255,255,0)"],
  grayColorAlpha: (opacity: number) => `rgba(200, 209, 232, ${opacity})`,
  welcome: {
    primaryText: "#fff",
    primaryTextAlpha: (alpha = 1) => `rgba(255,255,255,${alpha})`,
  },
}

And the problem is that I want to create an interface with dynamic properties, both for keys as a string, and if the key is callable as well.

2 Answers 2

3

Consider this exmaple:



type RGBA = `rgba(${number}, ${number}, ${number}, ${number})`

type Alpha = (opacity: number) => RGBA

type KeysHex = `${string}Color` | `${string}Text`

interface Data {
  [color: KeysHex]: `#${string}`
  [alpha: `${string}Alpha`]: Alpha
}

const foo: Data = {
  criticalColor: '2' // expected error
}

const bar: Data = {
  criticalColor: '#2' // ok, there is a limitation in TS
}

const baz: Data = {
  criticalColorAlpha: (opacity: number) => `rgba(1, 1, 1, ${opacity})` // ok
}

const baz2: Data = {
  criticalColorAlpha: (opacity: number) => `rgba(1, 1, 1, x)` // expected error
}

Playground

I have noticed, that you are using Alpha suffix if this is a method and Color or Text if it is a HEX color. This is why I have decided to use two different keys for Data interface.

You can use stonger types for RGBA but there is a limitation. Please see my article and this answer.

The same story about HEX colors. Please see this article.

Please provide all scenarios or restrictions and I will try to provide you with the most safest type.

Thank you

UPDATE The syntax you have used in your comment:

  [key in AdditionalKeysHex]:`#${string}`|string[];

is wrong. You are allowed to use in operator only in mapped types. In order to achieve desired behavior, I think Data interface should be splitted.

Please see DataResult type:

type RGBA = `rgba(${number}, ${number}, ${number}, ${number})`

type Alpha = (opacity: number) => RGBA

type KeysHex = `${string}Color` | `${string}Text` | `${string}Icon` | `${string}Background`;

const arr = ['white', 'darkGrayBlue', 'secondDarkGrayBlue', 'thirdDarkGrayBlue', 'darkDullBlue', 'secondDarkDullBlue', 'lightGrayBlue', 'secondLightGrayBlue', 'thirdLightGrayBlue', 'fourthLightGrayBlue', 'fifthLighGrayBlue', 'lightGrayNavy', 'paleNavy', 'brightBlue']

type AdditionalKeysHex = 'white' | 'darkGrayBlue' | 'secondDarkGrayBlue' | 'thirdDarkGrayBlue' | 'darkDullBlue' | 'secondDarkDullBlue' | 'lightGrayBlue' | 'secondLightGrayBlue' | 'thirdLightGrayBlue' | 'fourthLightGrayBlue' | 'fifthLighGrayBlue' | 'lightGrayNavy' | 'paleNavy' | 'brightBlue';

interface IWelcome {
  [color: KeysHex]: `#${string}` | string[];
  [alpha: `${string}Alpha`]: Alpha;
}


type WithKey = {
  [key in AdditionalKeysHex]: `#${string}` | string[];

}

interface Data {
  [color: KeysHex]: `#${string}` | string[];
  [alpha: `${string}Alpha`]: Alpha;
  welcome: IWelcome;
}

type DataResult = WithKey & Data

const Palette: DataResult = {
  primaryText: "#58585B",
  secondaryText: "#39393B",
  secondaryIcon: "#C8D1E8",
  tertiaryText: "#8F8E94",
  smallWidgetBackground: ["rgba(255,255,255,0.15)", "rgba(255,255,255,0)"],
  grayColorAlpha: (opacity: number) => `rgba(200, 209, 232, ${opacity})`,
  primaryTextAlpha: (opacity: number = 1) => `rgba(255, 255, 255, ${opacity})`,
  welcome: {
    primaryText: "#fff",
    primaryTextAlpha: (opacity: number = 1) => `rgba(255, 255, 255, ${opacity})`,
    secondaryText: "#C8D1E8",
    loaderColor: "#fff",
  },
  white: '#FFFFFF',
  darkGrayBlue: '#363C52',
};


Playground

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

8 Comments

You can add Icon to KeysHex. Do you have a naming pattern ?
@Olek I will back in several hours. Sorry
I'm also Ukrainian. Currently in Odesa:)
@Olek it is nice to hear. Wish you silent night
Wish you the same!)
|
0

you can remove the specific keys:

export type AlphaColorProcessing = (opacity: number) => string;

export interface Styles {
  [key: string]: string | AlphaColorProcessing;
}

3 Comments

This is what i did at the first time, error that I got: This expression is not callable. Not all constituents of type 'string | string[] | welcomeMapping | alphaColorProcessing' are callable. Type 'string' has no call signatures
this makes the keys optional which might not be what OP wants
how are you using it, u can add a typeguard before calling the styling

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.