Problem
In monorepo setups where packages are consumed as source (no separate build step), the leaf app's CustomTypeOptions.resources module augmentation must include all namespaces from all dependencies — even ones it never uses directly in its own code.
This is because CustomTypeOptions uses global module augmentation via declare module "i18next", and there's only one resources declaration for the entire app. Each package cannot independently declare just its own namespace types.
Example
Given a turborepo with:
apps/frontend (Next.js app)
packages/ui (shared component library with its own @repo/ui namespace)
For example: The frontend's augs.d.ts here must declare the UI package's namespace too, even though it never uses it directly:
declare module "i18next" {
interface CustomTypeOptions {
resources: {
// Frontend's own namespaces — properly typed
common: typeof common;
"page-home": typeof pageHome;
// ...
// Dependency namespace — forced to use `any` as a bandaid
"@repo/ui": any;
};
}
}
Without this, TypeScript errors on useTranslation("@repo/ui") calls inside the UI package code that the frontend consumes.
Current workaround
Declare dependency namespaces as any. This works but loses type safety for those cross-package namespaces.
Why TypeScript project references don't help
Potential directions
No concrete proposal yet — this issue tracks the limitation and collects ideas. Some possibilities:
- Per-package type declarations that merge automatically
- A generic parameter on hooks to scope type context per package
- Build-time tooling to generate a merged augmentation file
- A composable type helper utility
Context
Discussed in #1604
Problem
In monorepo setups where packages are consumed as source (no separate build step), the leaf app's
CustomTypeOptions.resourcesmodule augmentation must include all namespaces from all dependencies — even ones it never uses directly in its own code.This is because
CustomTypeOptionsuses global module augmentation viadeclare module "i18next", and there's only oneresourcesdeclaration for the entire app. Each package cannot independently declare just its own namespace types.Example
Given a turborepo with:
apps/frontend(Next.js app)packages/ui(shared component library with its own@repo/uinamespace)For example: The frontend's
augs.d.tshere must declare the UI package's namespace too, even though it never uses it directly:Without this, TypeScript errors on
useTranslation("@repo/ui")calls inside the UI package code that the frontend consumes.Current workaround
Declare dependency namespaces as
any. This works but loses type safety for those cross-package namespaces.Why TypeScript project references don't help
Potential directions
No concrete proposal yet — this issue tracks the limitation and collects ideas. Some possibilities:
Context
Discussed in #1604