From 00f94194388603840859681585192e4d00b22b87 Mon Sep 17 00:00:00 2001 From: Aral Roca Date: Mon, 17 Jul 2023 19:15:09 +0200 Subject: [PATCH 1/2] feat: add Paths type for type safety --- .../with-app-directory/next-translate.d.ts | 23 +++++++++ src/index.tsx | 51 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 examples/with-app-directory/next-translate.d.ts diff --git a/examples/with-app-directory/next-translate.d.ts b/examples/with-app-directory/next-translate.d.ts new file mode 100644 index 0000000..ea3fac6 --- /dev/null +++ b/examples/with-app-directory/next-translate.d.ts @@ -0,0 +1,23 @@ +import type { Paths, I18n, Translate } from 'next-translate' + +export interface TranslationsKeys { + common: Paths + home: Paths +} + +export interface TypeSafeTranslate + extends Omit { + t: { + ( + key: TranslationsKeys[Namespace], + ...rest: Tail> + ): string + (template: TemplateStringsArray): string + } +} + +declare module 'next-translate/useTranslation' { + export default function useTranslation< + Namespace extends keyof TranslationsKeys + >(namespace: Namespace): TypeSafeTranslate +} diff --git a/src/index.tsx b/src/index.tsx index 407ff6f..98ebc1f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -143,6 +143,57 @@ declare global { } } +//////// For type safety (next-translate.d.ts): /////////// +/* + * + * import type { Paths, I18n, Translate } from "next-translate"; + * + * export interface TranslationsKeys { + * common: Paths; + * home: Paths; + * } + * + * export interface TypeSafeTranslate + * extends Omit { + * t: { + * (key: TranslationsKeys[Namespace], ...rest: Tail>): string; + * (template: TemplateStringsArray): string; + * }; + * } + * + * declare module "next-translate/useTranslation" { + * export default function useTranslation< + * Namespace extends keyof TranslationsKeys, + * >(namespace: Namespace): TypeSafeTranslate; + * } + */ + +type RemovePlural = Key extends `${infer Prefix}${ + | '_zero' + | '_one' + | '_two' + | '_few' + | '_many' + | '_other' + | `_${infer Num}`}` + ? Prefix + : Key + +type Join = S1 extends string + ? S2 extends string + ? `${S1}.${S2}` + : never + : never + +// @ts-ignore +export type Paths = RemovePlural< + { + [K in keyof T]: T[K] extends Record + ? Join> + : K + }[keyof T] +> + // TODO: Remove this in future versions > 2.0.0 function nextTranslate(nextConfig: NextConfig = {}): NextConfig { console.log(` From 8489f69a46ca8934a988fa07dea596f4538d6ef1 Mon Sep 17 00:00:00 2001 From: Aral Roca Date: Mon, 17 Jul 2023 19:53:48 +0200 Subject: [PATCH 2/2] fix to satisfy the constraint 'string' --- src/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 98ebc1f..d1dc7eb 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -187,11 +187,13 @@ type Join = S1 extends string // @ts-ignore export type Paths = RemovePlural< + // @ts-ignore { - [K in keyof T]: T[K] extends Record + // @ts-ignore + [K in Extract]: T[K] extends Record ? Join> : K - }[keyof T] + }[Extract] > // TODO: Remove this in future versions > 2.0.0