Skip to content
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

add generic type to t function and the tests #665

Merged
merged 13 commits into from
Jan 18, 2019
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
"eslint-plugin-jsx-a11y": "6.1.1",
"eslint-plugin-prettier": "2.7.0",
"eslint-plugin-react": "7.11.1",
"i18next": "13.1.0",
"i18next": "^13.1.4",
"jest": "23.6.0",
"jest-cli": "23.6.0",
"mkdirp": "0.5.1",
Expand All @@ -79,7 +79,7 @@
"yargs": "12.0.2"
},
"peerDependencies": {
"i18next": ">= 6.0.1",
"i18next": ">= 13.1.3",
"react": ">= 16.3.0"
},
"scripts": {
Expand Down
8 changes: 3 additions & 5 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ export function setI18n(instance: i18next.i18n): void

export function getI18n(): i18next.i18n

export interface I18nContextValues {
export interface I18nContextValues extends i18next.WithT {
i18n: i18next.i18n
t: i18next.TranslationFunction
defaultNS?: string
reportNS?: string
lng?: string
Expand Down Expand Up @@ -74,7 +73,7 @@ export interface NamespacesConsumerProps extends ReactI18NextOptions {
initialI18nStore?: {}
initialLanguage?: string
children: (
t: i18next.TranslationFunction,
t: i18next.WithT['t'],
options: {
i18n: i18next.i18n
lng: string
Expand All @@ -94,12 +93,11 @@ export interface I18nextProviderProps {

export const I18nextProvider: React.ComponentClass<I18nextProviderProps>

export interface TransProps {
export interface TransProps extends Partial<i18next.WithT>{
i18nKey?: string
count?: number
parent?: React.ReactNode
i18n?: i18next.i18n
t?: i18next.TranslationFunction
defaults?: string
values?: {}
components?: React.ReactNode[]
Expand Down
86 changes: 86 additions & 0 deletions test/typescript/GenericTlanslateFunction.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import * as React from "react";
import {
NamespacesConsumer,
Trans,
withNamespaces,
WithNamespaces,
} from 'react-i18next';

type TKeys = "title" | "text";

function NamespacesConsumerTest() {
return (
<NamespacesConsumer>
{(t, { i18n }) =>
<div>
<h2>{t<TKeys>("title")}</h2>
<span>{t("any")}</span>
<span>{t("any", {anyObject: {}})}</span>
<span>{t<TKeys>("text")}</span>
<span>{t<TKeys, {key: string}>("text", {key: "foo"})}</span>
<span>{t<TKeys, {key: "bar"}, string>("text", {key: "bar"})}</span>
</div>
}
</NamespacesConsumer>
);
}

function TransComponentTest({ t }: WithNamespaces) {
return (
<div>
<Trans i18nKey="description.part1">
To get started, edit <code>src/App.js</code> and save to reload.
</Trans>
<Trans i18nKey="description.part1">
To get started, <strong title={t<TKeys>("title")}>{{name}}</strong>and save to reload.
</Trans>
</div>
);
}

const MyComponentWrapped = withNamespaces()(TransComponentTest);

type ArticleKeys = "article.part1" | "article.part2";
type AnotherArticleKeys = "anotherArticle.part1" | "anotherArticle.part2";

/**
* Overload makes completion of arguments by without specifying type parameters
*/
interface OverloadedWithNamespaces extends WithNamespaces {
t(key: ArticleKeys, b?: object): any;
// NOTION: disable no-unnecessary-generics for generic test
// tslint:disable-next-line:no-unnecessary-generics
t<T extends AnotherArticleKeys>(key: T, b: {name: string}): any;
}

class App extends React.Component<OverloadedWithNamespaces> {
render() {
const { t, i18n } = this.props;

const changeLanguage = (lng: string) => {
i18n.changeLanguage(lng);
};

return (
<div className="App">
<div className="App-header">
<NamespacesConsumerTest />
<button onClick={() => changeLanguage("de")}>de</button>
<button onClick={() => changeLanguage("en")}>en</button>
</div>
<div className="App-intro">
<MyComponentWrapped />
</div>
<article>
<div>{t("article.part1", {name: "foo"})}</div>
<div>{t("article.part2")}</div>
</article>
<article>
<div>{t<AnotherArticleKeys>("anotherArticle.part1", {name: "foo"})}</div>
<div>{t<AnotherArticleKeys>("anotherArticle.part2", {name: "bar"})}</div>
</article>
</div>
);
}
}
export default withNamespaces("translation")(App);