Search code examples
reactjstypescripttailwind-css

Extend tailwind config with typescript


I have a problem: I'm trying to use custom Tailwind colors in an enum, but TypeScript doesn't recognize the properties even though they are defined in my Tailwind configuration and type definitions:

import type { Config } from "tailwindcss";

const config: Config = {
  theme: {
    extend: {
      colors: {
        voteYes: "#10B981",
        voteNo: "#F43F5E",
        voteAbstain: "#6B7280",
      },
    },
  },
};
export default config;

I added the file tailwind.d.ts:

import "tailwindcss/tailwind-config";

declare module "tailwindcss/tailwind-config" {
  interface DefaultColors {
    voteYes: string;
    voteNo: string;
    voteAbstain: string;
  }
}

And I'm using it in my react component:

import resolveConfig from "tailwindcss/resolveConfig";
import tailwindConfig from "@/tailwind.config";

const fullConfig = resolveConfig(tailwindConfig);
const colors = fullConfig.theme?.colors;

enum VoteColor {
  yes = colors?.voteYes,
  no = colors?.voteNo,
  abstain = colors?.voteAbstain,
}

type VoteType = "yes" | "no" | "abstain";

const getColor = (vote: VoteType): string => {
  return VoteColor[vote] + "";
};

But I have this ts error for all the vote properties:

Property 'voteYes' does not exist on type 'DefaultColors'.

What am I missing?


Solution

  • resolveConfig doesnt merge the object like TS likes it, you havve to make a type for the colors, then refactor the enums

    Explicit type for colors

    type CustomColors = {
      voteYes: string;
      voteNo: string;
      voteAbstain: string;
    };
    

    VoteColorEnum

    import resolveConfig from "tailwindcss/resolveConfig";
    import tailwindConfig from "@/tailwind.config";
    
    const fullConfig = resolveConfig(tailwindConfig) as { theme: { colors: CustomColors } };
    const colors = fullConfig.theme.colors;
    
    const VoteColor = {
      yes: colors.voteYes,
      no: colors.voteNo,
      abstain: colors.voteAbstain,
    };
    

    then change the getColor function

    type VoteType = "yes" | "no" | "abstain";
    
    const getColor = (vote: VoteType): string => {
      return VoteColor[vote];
    };
    
    

    now you can use VoteColor in the getColor function