Home > database >  Making a Dynamic callable typescript interface property
Making a Dynamic callable typescript interface property

Time:05-02

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

{
  criticalColor: '#EF5350',
  warningColor: '#FFCA28',
  smallWidgetBackground: ["rgba(255,255,255,0.15)", "rgba(255,255,255,0)"],
  grayColorAlpha: (opacity: number) => `rgba(200, 209, 232, ${opacity})`,
  criticalColorAlpha: (opacity: number) => `rgba(239, 83, 80, ${opacity})`,
  welcome: {
    primaryText: "#fff",
    primaryTextAlpha: (alpha = 1) => `rgba(255,255,255,${alpha})`,
    secondaryText: "#C8D1E8",
    loaderColor: "#fff",
  },
}

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. This is what I can do, but it looks not so well, looking for a way to avoid repeating logic:

export type alphaColorProcessing = (opacity: number) => string | string[];

export interface welcomeMapping {
  [key: string]: alphaColorProcessing | string;
}
    
export interface IPalette {
  [key: string]: string | string[] | alphaColorProcessing | welcomeMapping;
  grayColorAlpha: alphaColorProcessing;
  criticalColorAlpha: alphaColorProcessing;
}

I tried something like :

export interface IPalette {
  [key: string]: string | string[] | alphaColorProcessing | welcomeMapping;
}

but in this case, I am getting an error:

This expression is not callable. Not all constituents of type 'string | string[] | welcomeMapping | alphaColorProcessing' are callable.Type 'string' has no call signatures.ts(2349)

CodePudding user response:

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

CodePudding user response:

you can remove the specific keys:

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

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