Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use TailwindCSS's resolve config with Typescript

I'm importing the following code into my .tsx component:

import resolveConfig from 'tailwindcss/resolveConfig';
import tailwindConfig from '../../../tailwind.config.js';

const fullConfig = resolveConfig(tailwindConfig)

If I then reference fullConfig.theme.colors["blue"]["700"] I get an error saying:

Element implicitly has an 'any' type because expression of type '"blue"' can't be used to index type 'TailwindThemeColors'. Property 'blue' does not exist on type 'TailwindThemeColors'.

The Tailwind type definition for colors is:

export type TailwindColorValue = string | TailwindColorGroup | TailwindColorFunction;

export interface TailwindValuesColor {
    readonly [key: string]: TailwindColorValue;
}

Since the type does not explicitly say that "blue" is a value and that it could be an object, that's the cause of the error (I think).

An additional problem I'm getting is an error in my tsconfig.json, because I'm importing a JS file. Adding "exclude": ["tailwind.config.js"] doesn't solve the issue.

I'm pretty sure this is a Typescript issue more than a Tailwind one...

My questions are:

  1. How can I make Typescript aware of the "blue" property on the colors in my tailwind theme, and
  2. How can I stop the tsconfig error from importing the JS config?
like image 420
Raph117 Avatar asked Sep 13 '25 14:09

Raph117


2 Answers

Answering the original question #1.
Somehow, typescript can't give you correct typings when doing like so:

import tailwindConfig from 'tailwind-config'
// or so:
import * as tailwindConfig from 'tailwind-config'

So I figured, that I actually only need the theme (and the content is just required in Config type) and ended up like this:

import { content, theme } from 'tailwind-config'; // just an alias for the tailwind.config.js
import resolveConfig from 'tailwindcss/resolveConfig';

const fullConfig = resolveConfig({
  content,
  theme,
});

const foo = fullConfig.theme.colors['black-1']; // foo: string;

The only problem here is I can't have /** @type {import('tailwindcss').Config} */ in the config file itself, because IDE starts to resolve types from there instead of the config objects. But it's mainly an IDE problem and probably resolvable too.


As for question #2, I believe adding "allowJs": true in the compilerOptions of tsconfig.json will do the trick.

like image 68
kuzkokov Avatar answered Sep 15 '25 04:09

kuzkokov


This looks like it's a problem occurring because of the union types that Tailwind has typed its resolveConfig return value with. Essentially, because of the union, TS doesn't know whether the value of fullConfig.theme.colors is an object or a getter function (and likewise, whether fullConfig.theme.colors["blue"] is a string, color-group object or a color function) - presumably this is because this decision is left to the user's tailwind.conf implementation choices, and Tailwind doesn't infer it.

The easiest way to get around this would probably be to write your own function that takes the union-typed value you're trying to use and returns only the specific type you want, eg.

import _ from 'lodash';

const asColorObject = (
  input: TailwindThemeColors | undefined,
): Exclude<typeof input, Function | undefined> => {
  if (_.isFunction(input) || !input) throw new Error();
  return input;
};

const fullConfig = resolveConfig(tailwindConfig);
const colorBlue = asColorObject(fullConfig.theme.colors)['blue'];

In terms of why importing your Tailwind config is giving you errors, check your allowJs and checkJS keys in compilerOptions in your TSConfig. Otherwise, if you're using Create React App, it won't be possible this way at all since you can't import files from outside the src folder.

like image 42
Geoff Davids Avatar answered Sep 15 '25 02:09

Geoff Davids