diff --git a/test/typescript/custom-types/custom-types.d.ts b/test/typescript/custom-types/custom-types.d.ts index d0c37349..5fc5e8e4 100644 --- a/test/typescript/custom-types/custom-types.d.ts +++ b/test/typescript/custom-types/custom-types.d.ts @@ -10,6 +10,9 @@ declare module 'react-i18next' { }; alternate: { baz: 'baz'; + foobar: { + barfoo: 'barfoo'; + }; }; }; } diff --git a/test/typescript/custom-types/useTranslation.test.tsx b/test/typescript/custom-types/useTranslation.test.tsx index b7ad63d3..b2f0b300 100644 --- a/test/typescript/custom-types/useTranslation.test.tsx +++ b/test/typescript/custom-types/useTranslation.test.tsx @@ -38,6 +38,11 @@ function readonlyArrayNamespace() { ); } +function keyPrefixOption() { + const [t] = useTranslation('alternate', { keyPrefix: 'foobar' }); + return <>{t('barfoo')}; +} + function expectErrorWhenNamespaceDoesNotExist() { // @ts-expect-error const [t] = useTranslation('fake'); @@ -61,3 +66,15 @@ function expectErrorWhenUsingArrayNamespaceAndWrongKey() { // @ts-expect-error return <>{t('custom:fake')}; } + +function expectErrorWhenUsingWrongKeyPrefixOption() { + // @ts-expect-error + const [t] = useTranslation('alternate', { keyPrefix: 'abc' }); + return <>{t('barfoo')}; +} + +function expectErrorWhenUsingRightKeyPrefixOptionAndWrongKey() { + const [t] = useTranslation('alternate', { keyPrefix: 'foobar' }); + // @ts-expect-error + return <>{t('abc')}; +} diff --git a/ts4.1/index.d.ts b/ts4.1/index.d.ts index cd5c50ac..6c76562f 100644 --- a/ts4.1/index.d.ts +++ b/ts4.1/index.d.ts @@ -149,12 +149,20 @@ type NormalizeMultiReturn = V extends `${infer N}:${infer R}` : never : never; -export type TFuncKey = N extends - | (keyof T)[] - | Readonly<(keyof T)[]> +type KeyPrefix = N extends keyof DefaultResources + ? Fallback | undefined + : string | undefined; + +export type TFuncKey< + N extends Namespace = DefaultNamespace, + TKPrefix extends KeyPrefix = undefined, + T = DefaultResources +> = N extends (keyof T)[] | Readonly<(keyof T)[]> ? NormalizeMulti : N extends keyof T - ? Normalize + ? TKPrefix extends keyof T[N] + ? Normalize + : Normalize : string; export type TFuncReturn = N extends (keyof T)[] @@ -163,9 +171,12 @@ export type TFuncReturn = N exte ? NormalizeReturn : Fallback; -export interface TFunction { +export interface TFunction< + N extends Namespace = DefaultNamespace, + TKPrefix extends KeyPrefix = undefined +> { < - TKeys extends TFuncKey | TemplateStringsArray extends infer A ? A : never, + TKeys extends TFuncKey | TemplateStringsArray extends infer A ? A : never, TDefaultResult extends TFunctionResult = string, TInterpolationMap extends object = StringMap >( @@ -173,7 +184,7 @@ export interface TFunction { options?: TOptions | string, ): TFuncReturn; < - TKeys extends TFuncKey | TemplateStringsArray extends infer A ? A : never, + TKeys extends TFuncKey | TemplateStringsArray extends infer A ? A : never, TDefaultResult extends TFunctionResult = string, TInterpolationMap extends object = StringMap >( @@ -208,22 +219,32 @@ export function Trans< export function useSSR(initialI18nStore: Resource, initialLanguage: string): void; -export interface UseTranslationOptions { +export interface UseTranslationOptions< + N extends Namespace = DefaultNamespace, + TKPrefix extends KeyPrefix = undefined +> { i18n?: i18n; useSuspense?: boolean; - keyPrefix?: string; + keyPrefix?: TKPrefix; } -type UseTranslationResponse = [TFunction, i18n, boolean] & { - t: TFunction; +type UseTranslationResponse> = [ + TFunction, + i18n, + boolean, +] & { + t: TFunction; i18n: i18n; ready: boolean; }; -export function useTranslation( +export function useTranslation< + N extends Namespace = DefaultNamespace, + TKPrefix extends KeyPrefix = undefined +>( ns?: N | Readonly, - options?: UseTranslationOptions, -): UseTranslationResponse; + options?: UseTranslationOptions, +): UseTranslationResponse; // Need to see usage to improve this export function withSSR(): (