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
- Create an Expo/React Native project with this
tsconfig.json:
{
"compilerOptions": {
"moduleSuffixes": [".ios", ".android", ".native", ""]
}
}
- 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
}
- 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
What happened?
When using TypeScript's
moduleSuffixesoption, theThemeNametype is not properly resolved becauseconfig.native.d.tsdoes not re-export it.This causes
useUniwind()to return an error-typed value for thethemeproperty, breaking type safety and triggering ESLint errors like:Root Cause
The issue is in the type declaration files:
dist/module/core/config/config.d.ts(line 3):✅ Correctly exports
ThemeNamedist/module/core/config/config.native.d.ts:❌ Missing:
export { type ThemeName } from './config.common';When
moduleSuffixes: [".ios", ".android", ".native", ""]is set intsconfig.json, TypeScript resolves./configtoconfig.native.d.tsinstead ofconfig.d.ts. Sinceconfig.native.d.tsdoesn't exportThemeName, the type becomes unresolved.Expected Behavior
ThemeNameshould be properly exported fromconfig.native.d.tsso thatuseUniwind()returns correctly typed values regardless ofmoduleSuffixesconfiguration.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
Workaround
Remove
moduleSuffixesfromtsconfig.json, or don't include.nativein the suffixes array. However, this may break other platform-specific type resolution in React Native projects.Steps to Reproduce
tsconfig.json:{ "compilerOptions": { "moduleSuffixes": [".ios", ".android", ".native", ""] } }useUniwind():themehas 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