Skip to content

Commit

Permalink
Merge 821d264 into f78fa2b
Browse files Browse the repository at this point in the history
  • Loading branch information
sreucherand committed Jan 9, 2024
2 parents f78fa2b + 821d264 commit 03c563d
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 7 deletions.
5 changes: 5 additions & 0 deletions test/typescript/array-access/i18next.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ declare module 'i18next' {
{ fizz: 'buzz' },
[{ test: 'success'; sub: { deep: 'still success' } }],
];
arrayJoinWithInterpolation_one: ['{{myName}}, You have', '{{count}}', 'email'];
arrayJoinWithInterpolation_other: ['{{myName}}, You have', '{{count}}', 'emails'];
key_one: 'item';
key_other: 'items';
nestedArrayJoin: [['line1', 'line2', 'line3']];
};
ctx: {
dessert: [
Expand Down
18 changes: 18 additions & 0 deletions test/typescript/array-access/t.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,24 @@ describe('main', () => {
expectTypeOf(t('arrayOfObjects.0', { returnObjects: true })).toEqualTypeOf<{ foo: 'bar' }>();
});

it('should work with `count`', () => {
expectTypeOf(t('key', { count: 1 })).toEqualTypeOf<'item' | 'items'>();
});

it('should work with `joinArrays`', () => {
expectTypeOf(t('arrayOfStrings', { joinArrays: '+' })).toEqualTypeOf<'zero+one'>();
expectTypeOf(t('arrayOfObjects', { joinArrays: '+' })).toEqualTypeOf<never>();
expectTypeOf(t('nestedArrayJoin.0', { joinArrays: '/' })).toEqualTypeOf<'line1/line2/line3'>();
expectTypeOf(
t('arrayJoinWithInterpolation', { count: 2, myName: 'Claude', joinArrays: ' ' }),
).toEqualTypeOf<
'{{myName}}, You have {{count}} email' | '{{myName}}, You have {{count}} emails'
>();
expectTypeOf(
t('readonlyArrayOfStrings', { joinArrays: ',' }),
).toEqualTypeOf<'readonly zero,readonly one'>();
});

it('should work with const keys', () => {
const alternateTranslationKeys = ['arrayOfStrings.0', 'arrayOfObjects.0.foo'] as const;

Expand Down
7 changes: 7 additions & 0 deletions typescript/helpers.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@ export type $Dictionary<T = unknown> = { [key: string]: T };
export type $OmitArrayKeys<Arr> = Arr extends readonly any[] ? Omit<Arr, keyof any[]> : Arr;
export type $PreservedValue<Value, Fallback> = [Value] extends [never] ? Fallback : Value;
export type $SpecialObject = object | Array<string | object>;
export type $PrependIfDefined<T extends string, S extends string> = T extends '' ? T : `${S}${T}`;
export type $ConcatArray<T, S extends string, U = never> = T extends readonly [
infer F extends string,
...infer R extends string[],
]
? `${F}${$PrependIfDefined<$ConcatArray<R, S, ''>, S>}`
: U;
5 changes: 5 additions & 0 deletions typescript/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ export type TypeOptions = $MergeBy<
* Suffix for interpolation
*/
interpolationSuffix: '}}';

/**
* A string to separate each pair of adjacent elements of the array
*/
joinArrays: false;
},
CustomTypeOptions
>;
Expand Down
31 changes: 24 additions & 7 deletions typescript/t.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import type { $OmitArrayKeys, $PreservedValue, $Dictionary, $SpecialObject } from './helpers.js';
import type {
$ConcatArray,
$OmitArrayKeys,
$PreservedValue,
$Dictionary,
$SpecialObject,
} from './helpers.js';
import type {
TypeOptions,
Namespace,
Expand All @@ -11,6 +17,7 @@ import type {
/* eslint @typescript-eslint/ban-types: ['error', { types: { "{}": false } }] */

// Type Options
type _JoinArrays = TypeOptions['joinArrays'];
type _ReturnObjects = TypeOptions['returnObjects'];
type _ReturnNull = TypeOptions['returnNull'];
type _KeySeparator = TypeOptions['keySeparator'];
Expand Down Expand Up @@ -83,7 +90,9 @@ type ResourceKeys<WithReturnObjects = _ReturnObjects> = WithReturnObjects extend
/** **********************************************************************
* Parse t function keys based on the namespace, options and key prefix *
*********************************************************************** */
export type KeysByTOptions<TOpt extends TOptions> = TOpt['returnObjects'] extends true
export type KeysByTOptions<TOpt extends TOptions> = TOpt['joinArrays'] extends string
? ResourceKeys<true>
: TOpt['returnObjects'] extends true
? ResourceKeys<true>
: ResourceKeys;

Expand Down Expand Up @@ -157,6 +166,10 @@ type ParseTReturnPluralOrdinal<
string}${_PluralSeparator}ordinal${_PluralSeparator}${PluralSuffix}`,
> = Res[(KeyWithOrdinalPlural | Key) & keyof Res];

type ParseTReturnJoinArrays<Ret, TOpt extends TOptions = {}> = TOpt['joinArrays'] extends string
? $ConcatArray<Ret, TOpt['joinArrays']>
: Ret;

type ParseTReturn<
Key,
Res,
Expand All @@ -166,17 +179,21 @@ type ParseTReturn<
: // Process plurals only if count is provided inside options
TOpt['count'] extends number
? TOpt['ordinal'] extends boolean
? ParseTReturnPluralOrdinal<Res, Key>
: ParseTReturnPlural<Res, Key>
? ParseTReturnJoinArrays<ParseTReturnPluralOrdinal<Res, Key>, TOpt>
: ParseTReturnJoinArrays<ParseTReturnPlural<Res, Key>, TOpt>
: // otherwise access plain key without adding plural and ordinal suffixes
Res extends readonly unknown[]
? Key extends `${infer NKey extends number}`
? Res[NKey]
? ParseTReturnJoinArrays<Res[NKey], TOpt>
: never
: Res[Key & keyof Res];
: ParseTReturnJoinArrays<Res[Key & keyof Res], TOpt>;

type TReturnOptionalNull = _ReturnNull extends true ? null : never;
type TReturnOptionalObjects<TOpt extends TOptions> = _ReturnObjects extends true
type TReturnOptionalObjects<TOpt extends TOptions> = _JoinArrays extends string
? string
: TOpt['joinArrays'] extends string
? string
: _ReturnObjects extends true
? $SpecialObject | string
: TOpt['returnObjects'] extends true
? $SpecialObject
Expand Down

0 comments on commit 03c563d

Please sign in to comment.