Skip to content

Typing of 't' function when used as parameter inside a function #500

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
fitimbytyqi opened this issue Sep 6, 2023 · 9 comments
Closed
Labels
enhancement New feature or request unconfirmed Needs triage.

Comments

@fitimbytyqi
Copy link

fitimbytyqi commented Sep 6, 2023

Is your feature request related to a problem? Please describe.

Currently, I have a function that accepts the t function from useTranslations.

e.x const columns = (t: 'some type') => [...data];

The type of t was a bit difficult to find because it's not exported from the package as far as am aware?

Describe the solution you'd like

What I would want to have is an exported type from the package which is easier to be found for beginners of this package.

e.x const columns = (t: TFunction) => [...data];

Describe alternatives you've considered

Right now, I have created my own interface which extends from the package which looks like this.

I can also make a pull request if needed for this solution, please let me know ;)

export interface TFunction<
  NestedKey extends NamespaceKeys<
    IntlMessages,
    NestedKeyOf<IntlMessages>
  > = never
> {
  <
    TargetKey extends MessageKeys<
      NestedValueOf<
        {
          '!': IntlMessages;
        },
        [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
      >,
      NestedKeyOf<
        NestedValueOf<
          {
            '!': IntlMessages;
          },
          [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
        >
      >
    >
 ... more lines ....
@fitimbytyqi fitimbytyqi added enhancement New feature or request unconfirmed Needs triage. labels Sep 6, 2023
@amannn
Copy link
Owner

amannn commented Sep 7, 2023

This is currently not supported by design, please see these previous discussions:

@amannn amannn closed this as completed Sep 7, 2023
@adarshaacharya
Copy link

adarshaacharya commented Sep 17, 2024

export interface TFunction<
NestedKey extends NamespaceKeys<
IntlMessages,
NestedKeyOf

= never
{
<
TargetKey extends MessageKeys<
NestedValueOf<
{
'!': IntlMessages;
},
[NestedKey] extends [never] ? '!' : !.${NestedKey}
>,
NestedKeyOf<
NestedValueOf<
{
'!': IntlMessages;
},
[NestedKey] extends [never] ? '!' : !.${NestedKey}
>
>
>

@fitimbytyqi can you share your whole interface of this.

export type TFunction<
  NestedKey extends NamespaceKeys<
    IntlMessages,
    NestedKeyOf<IntlMessages>
  > = never,
> = ReturnType<
  typeof useTranslations<
    NestedKey extends never ? NestedKeyOf<IntlMessages> : NestedKey
  >
>;

Here's what I'm using currently but its not that good.

@fitimbytyqi
Copy link
Author

export interface TFunction<
NestedKey extends NamespaceKeys<
IntlMessages,
NestedKeyOf

= never
{
<
TargetKey extends MessageKeys<
NestedValueOf<
{
'!': IntlMessages;
},
[NestedKey] extends [never] ? '!' : !.${NestedKey}

,
NestedKeyOf<
NestedValueOf<
{
'!': IntlMessages;
},
[NestedKey] extends [never] ? '!' : !.${NestedKey}

@fitimbytyqi can you share your whole interface of this.

export type TFunction<
  NestedKey extends NamespaceKeys<
    IntlMessages,
    NestedKeyOf<IntlMessages>
  > = never,
> = ReturnType<
  typeof useTranslations<
    NestedKey extends never ? NestedKeyOf<IntlMessages> : NestedKey
  >
>;

Here's what I'm using currently but its not that good.

Sure, here is the long version of it.

import { ReactElement, ReactNode } from 'react';
import {
  Formats,
  MessageKeys,
  NamespaceKeys,
  NestedKeyOf,
  NestedValueOf,
  RichTranslationValues,
  TranslationValues,
} from 'next-intl';

export interface TFunction<
  NestedKey extends NamespaceKeys<
    IntlMessages,
    NestedKeyOf<IntlMessages>
  > = never,
> {
  <
    TargetKey extends MessageKeys<
      NestedValueOf<
        {
          '!': IntlMessages;
        },
        [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
      >,
      NestedKeyOf<
        NestedValueOf<
          {
            '!': IntlMessages;
          },
          [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
        >
      >
    >,
  >(
    key: TargetKey,
    values?: TranslationValues,
    formats?: Partial<Formats>
  ): string;
  rich<
    TargetKey extends MessageKeys<
      NestedValueOf<
        {
          '!': IntlMessages;
        },
        [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
      >,
      NestedKeyOf<
        NestedValueOf<
          {
            '!': IntlMessages;
          },
          [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
        >
      >
    >,
  >(
    key: TargetKey,
    values?: RichTranslationValues,
    formats?: Partial<Formats>
  ): string | ReactElement | ReactNode;
  raw<
    TargetKey extends MessageKeys<
      NestedValueOf<
        {
          '!': IntlMessages;
        },
        [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
      >,
      NestedKeyOf<
        NestedValueOf<
          {
            '!': IntlMessages;
          },
          [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
        >
      >
    >,
  >(
    key: TargetKey
  ): any;
}

@adarshaacharya
Copy link

export interface TFunction<
NestedKey extends NamespaceKeys<
IntlMessages,
NestedKeyOf

= never
{
<
TargetKey extends MessageKeys<
NestedValueOf<
{
'!': IntlMessages;
},
[NestedKey] extends [never] ? '!' : !.${NestedKey}

,
NestedKeyOf<
NestedValueOf<
{
'!': IntlMessages;
},
[NestedKey] extends [never] ? '!' : !.${NestedKey}

@fitimbytyqi can you share your whole interface of this.

export type TFunction<
  NestedKey extends NamespaceKeys<
    IntlMessages,
    NestedKeyOf<IntlMessages>
  > = never,
> = ReturnType<
  typeof useTranslations<
    NestedKey extends never ? NestedKeyOf<IntlMessages> : NestedKey
  >
>;

Here's what I'm using currently but its not that good.

Sure, here is the long version of it.

import { ReactElement, ReactNode } from 'react';
import {
  Formats,
  MessageKeys,
  NamespaceKeys,
  NestedKeyOf,
  NestedValueOf,
  RichTranslationValues,
  TranslationValues,
} from 'next-intl';

export interface TFunction<
  NestedKey extends NamespaceKeys<
    IntlMessages,
    NestedKeyOf<IntlMessages>
  > = never,
> {
  <
    TargetKey extends MessageKeys<
      NestedValueOf<
        {
          '!': IntlMessages;
        },
        [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
      >,
      NestedKeyOf<
        NestedValueOf<
          {
            '!': IntlMessages;
          },
          [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
        >
      >
    >,
  >(
    key: TargetKey,
    values?: TranslationValues,
    formats?: Partial<Formats>
  ): string;
  rich<
    TargetKey extends MessageKeys<
      NestedValueOf<
        {
          '!': IntlMessages;
        },
        [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
      >,
      NestedKeyOf<
        NestedValueOf<
          {
            '!': IntlMessages;
          },
          [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
        >
      >
    >,
  >(
    key: TargetKey,
    values?: RichTranslationValues,
    formats?: Partial<Formats>
  ): string | ReactElement | ReactNode;
  raw<
    TargetKey extends MessageKeys<
      NestedValueOf<
        {
          '!': IntlMessages;
        },
        [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
      >,
      NestedKeyOf<
        NestedValueOf<
          {
            '!': IntlMessages;
          },
          [NestedKey] extends [never] ? '!' : `!.${NestedKey}`
        >
      >
    >,
  >(
    key: TargetKey
  ): any;
}

thanks !

I think this type utility should be exported from library itself, very useful and typesafe.

@fitimbytyqi
Copy link
Author

@adarshaacharya You are welcome, that would be nice but they don't plan on doing it, so we can use this as an alternative.

@danieljosue1233
Copy link

IntlMessages ???

@fplu
Copy link

fplu commented Dec 15, 2024

Unfortunately, the code given in this thread seems to be outdated (it doesn't work for me as well @danieljosue1233 ).
Nevertheless, this thread is well referenced by Google, so here's an up to date solution I've found by checking the return value of useTranslations that works for me.

import {
  Formats,
  MarkupTranslationValues,
  RichTranslationValues,
  TranslationValues,
} from 'next-intl';

export type TFunction = {
  <TargetKey>(key: TargetKey, values?: TranslationValues, formats?: Formats): string;
  rich<TargetKey>(key: TargetKey, values?: RichTranslationValues, formats?: Formats): React.ReactNode;
  markup<TargetKey>(key: TargetKey, values?: MarkupTranslationValues, formats?: Formats): string;
  raw<TargetKey>(key: TargetKey): any;
  has<TargetKey>(key: TargetKey): boolean;
};

@fitimbytyqi
Copy link
Author

Thank you for providing an updated solution, I haven't upgraded the package yet, but once I do I'll test this type out 👍

@FINDarkside
Copy link

The code above works, but one problem is that the value returned by useTranslations is not assignable to TFunction. Is there some reason to not just do this:

import type { createTranslator, Messages } from "next-intl";
export type TFunction = ReturnType<typeof createTranslator<Messages>>;

It seems to work at least for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request unconfirmed Needs triage.
Projects
None yet
Development

No branches or pull requests

6 participants