Skip to content

Commit

Permalink
feat: add Paths type for type safety (#1108)
Browse files Browse the repository at this point in the history
* feat: add Paths type for type safety

* fix to satisfy the constraint 'string'
  • Loading branch information
aralroca authored Jul 17, 2023
1 parent de5ad45 commit f152419
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
23 changes: 23 additions & 0 deletions examples/with-app-directory/next-translate.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Paths, I18n, Translate } from 'next-translate'

export interface TranslationsKeys {
common: Paths<typeof import('./locales/en/common.json')>
home: Paths<typeof import('./locales/en/home.json')>
}

export interface TypeSafeTranslate<Namespace extends keyof TranslationsKeys>
extends Omit<I18n, 't'> {
t: {
(
key: TranslationsKeys[Namespace],
...rest: Tail<Parameters<Translate>>
): string
<T extends string>(template: TemplateStringsArray): string
}
}

declare module 'next-translate/useTranslation' {
export default function useTranslation<
Namespace extends keyof TranslationsKeys
>(namespace: Namespace): TypeSafeTranslate<Namespace>
}
53 changes: 53 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,59 @@ declare global {
}
}

//////// For type safety (next-translate.d.ts): ///////////
/*
*
* import type { Paths, I18n, Translate } from "next-translate";
*
* export interface TranslationsKeys {
* common: Paths<typeof import("./locales/en/common.json")>;
* home: Paths<typeof import("./locales/en/home.json")>;
* }
*
* export interface TypeSafeTranslate<Namespace extends keyof TranslationsKeys>
* extends Omit<I18n, "t"> {
* t: {
* (key: TranslationsKeys[Namespace], ...rest: Tail<Parameters<Translate>>): string;
* <T extends string>(template: TemplateStringsArray): string;
* };
* }
*
* declare module "next-translate/useTranslation" {
* export default function useTranslation<
* Namespace extends keyof TranslationsKeys,
* >(namespace: Namespace): TypeSafeTranslate<Namespace>;
* }
*/

type RemovePlural<Key extends string> = Key extends `${infer Prefix}${
| '_zero'
| '_one'
| '_two'
| '_few'
| '_many'
| '_other'
| `_${infer Num}`}`
? Prefix
: Key

type Join<S1, S2> = S1 extends string
? S2 extends string
? `${S1}.${S2}`
: never
: never

// @ts-ignore
export type Paths<T> = RemovePlural<
// @ts-ignore
{
// @ts-ignore
[K in Extract<keyof T, string>]: T[K] extends Record<string, unknown>
? Join<K, Paths<T[K]>>
: K
}[Extract<keyof T, string>]
>

// TODO: Remove this in future versions > 2.0.0
function nextTranslate(nextConfig: NextConfig = {}): NextConfig {
console.log(`
Expand Down

0 comments on commit f152419

Please sign in to comment.