Romanchuk / angular-i18next

angular v10+ integration with i18next v19.4+
MIT License
131 stars 33 forks source link

New typings prevents passing interpolation to `ITranslationService` #106

Closed evantrimboli closed 1 year ago

evantrimboli commented 1 year ago

Reproduction: https://stackblitz.com/edit/typescript-jbfwwg

When trying to pass interpolation to the ITranslationService, I'm getting a typescript error:

i18n.t('greeting', { name: 'Hacker' }); // No overload matches this call

This is due to the recent change here: https://github.com/Romanchuk/angular-i18next/commit/62f21b32bb5c2377d2072633ed0d67f6b89fede1#diff-18a5fe5530a78ac5080909829e6f8343adb413588d23e1cae47d2082656c4cd2R28

I believe instead the type of the parameters should change from:

i18n.TOptionsBase & object & { defaultValue?: string; } to i18n.TOptionsBase & i18n.StringMap & { defaultValue?: string; }

If I modify the types that resolves the issue.

Full code for completeness:

import * as i18n from 'i18next';

interface ITranslationService {
  t(key: string | string[], options?: i18n.TOptionsBase & object & {
      defaultValue?: string;
  }): i18n.DefaultTFuncReturn;
}

interface ITranslationServiceStringMap {
  t(key: string | string[], options?: i18n.TOptionsBase & i18n.StringMap & {
      defaultValue?: string;
  }): i18n.DefaultTFuncReturn;
}

const service1 : ITranslationService = { t: () => '' };
const service2 : ITranslationServiceStringMap = { t: () => '' };

// bad
service1.t('some.string', { hello: 'there' })

// good
service2.t('some.string', { hello: 'there' })
vz-tl commented 1 year ago

In addition to the above, I observed errors when calling i18n.t() to return either an object or array of strings. A potential fix would be making t() method definition in ITranslationService a generic:

-    t(key: string | string[], options?: i18n.TOptionsBase & object & {
+    t<T extends i18n.DefaultTFuncReturnWithObject = i18n.DefaultTFuncReturn>(key: string | string[], options?: i18n.TOptionsBase & i18n.StringMap & {
         defaultValue?: string;
-    }): i18n.DefaultTFuncReturn;
+    }): T;
-    t(key: string | string[], defaultValue: string, options?: i18n.TOptionsBase & object & {
+    t<T extends i18n.DefaultTFuncReturnWithObject = i18n.DefaultTFuncReturn>(key: string | string[], defaultValue: string, options?: i18n.TOptionsBase & i18n.StringMap & {
         defaultValue: string;
-    }): i18n.DefaultTFuncReturn;
+    }): T;