Skip to content

ThemeName type not exported from uniwind, causing type errors with moduleSuffixes #245

Description

@pattobrien

What happened?

When using TypeScript's moduleSuffixes option, the ThemeName type is not properly resolved because config.native.d.ts does not re-export it.

This causes useUniwind() to return an error-typed value for the theme property, breaking type safety and triggering ESLint errors like:

Unsafe object destructuring of a property with an error typed value
@typescript-eslint/no-unsafe-assignment

Root Cause

The issue is in the type declaration files:

dist/module/core/config/config.d.ts (line 3):

export { type ThemeName } from './config.common';

✅ Correctly exports ThemeName

dist/module/core/config/config.native.d.ts:

import { Insets } from 'react-native';
import { CSSVariables, GenerateStyleSheetsCallback } from '../types';
import { ThemeName, UniwindConfigBuilder as UniwindConfigBuilderBase } from './config.common';
declare class UniwindConfigBuilder extends UniwindConfigBuilderBase {
    // ...
}
export declare const Uniwind: UniwindConfigBuilder;
export {};

Missing: export { type ThemeName } from './config.common';

When moduleSuffixes: [".ios", ".android", ".native", ""] is set in tsconfig.json, TypeScript resolves ./config to config.native.d.ts instead of config.d.ts. Since config.native.d.ts doesn't export ThemeName, the type becomes unresolved.

Expected Behavior

ThemeName should be properly exported from config.native.d.ts so that useUniwind() returns correctly typed values regardless of moduleSuffixes configuration.

Suggested Fix

Add the missing export to config.native.d.ts:

  import { Insets } from 'react-native';
  import { CSSVariables, GenerateStyleSheetsCallback } from '../types';
  import { ThemeName, UniwindConfigBuilder as UniwindConfigBuilderBase } from './config.common';
+ export { type ThemeName } from './config.common';
  declare class UniwindConfigBuilder extends UniwindConfigBuilderBase {
      constructor();
      __reinit(generateStyleSheetCallback: GenerateStyleSheetsCallback, themes: Array<string>): void;
      onThemeChange(): void;
      updateCSSVariables(theme: ThemeName, variables: CSSVariables): void;
      updateInsets(insets: Insets): void;
  }
  export declare const Uniwind: UniwindConfigBuilder;
- export {};

Environment

  • uniwind version: 1.2.2
  • TypeScript version: 5.x
  • React Native: 0.81.x
  • Expo: 54.x

Workaround

Remove moduleSuffixes from tsconfig.json, or don't include .native in the suffixes array. However, this may break other platform-specific type resolution in React Native projects.

Steps to Reproduce

  1. Create an Expo/React Native project with this tsconfig.json:
{
  "compilerOptions": {
    "moduleSuffixes": [".ios", ".android", ".native", ""]
  }
}
  1. Use useUniwind():
import { useUniwind } from 'uniwind';

function App() {
  const { theme } = useUniwind(); // theme has error type
  return <ThemeProvider value={NAV_THEME[theme]}> // Error: can't index with error type
}
  1. Observe that theme has an error type instead of 'light' | 'dark'

Snack or Repository Link

https://github.com/pattobrien/uniwind-theme-name-bug

Uniwind version

1.2.2

React Native Version

0.81.0

Platforms

iOS

Expo

Yes

Additional information

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions