Skip to content

Commit

Permalink
Adding unflatten to objects
Browse files Browse the repository at this point in the history
  • Loading branch information
kamaal111 committed May 20, 2024
1 parent 0985473 commit 478a6da
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * as maths from './maths';
export * as strings from './strings';
export * as arrays from './arrays';
export * as shell from './shell';
export * as types from './types';
6 changes: 4 additions & 2 deletions src/objects/flatten.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function _flatten<Result extends object>(
function _flatten<Result extends Record<string, unknown>>(
obj: Record<string, unknown>,
recursiveContext?: { parentKey: string; result: Result }
): Result {
Expand All @@ -17,7 +17,9 @@ function _flatten<Result extends object>(
}, initialResult);
}

function flatten<Result extends object>(obj: Record<string, unknown>): Result {
function flatten<Result extends Record<string, unknown>>(
obj: Record<string, unknown>
): Result {
return _flatten(obj);
}

Expand Down
1 change: 1 addition & 0 deletions src/objects/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './omit';
export * from './omitBy';
export * from './flatten';
export * from './unflatten';
25 changes: 25 additions & 0 deletions src/objects/unflatten.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import unflatten from './unflatten';

describe('unflatten', () => {
it('unflatten the given object', () => {
const flatObject = {
'hello.yes': 'true',
flat: 'yes',
'nested.array': [1, 2],
'furthernested.yes.no': false,
};

const result = unflatten(flatObject, '.');

expect(result).toEqual({
hello: {
yes: 'true',
},
flat: 'yes',
nested: {
array: [1, 2],
},
furthernested: { yes: { no: false } },
});
});
});
33 changes: 33 additions & 0 deletions src/objects/unflatten.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { NonEmptyArray } from '../types/arrays';
import type { Character } from '../types/strings';

function setNestedValue<Result extends object>(
obj: Result,
keys: NonEmptyArray<string>,
value: unknown
): Result {
const [first, ...rest] = keys;
if (rest.length === 0) return { ...obj, [first]: value };

const nestedObject = (obj as Record<string, unknown>)[first] ?? {};

return {
...obj,
[first]: setNestedValue(nestedObject, rest as NonEmptyArray<string>, value),
};
}

function unflatten<Result extends object, Delimiter extends string>(
data: object,
delimiter: Character<Delimiter>
): Result {
const initialResult = {} as unknown as Result;

return Object.entries(data).reduce<Result>((acc, [key, value]) => {
const keys = key.split(delimiter) as NonEmptyArray<string>;

return setNestedValue(acc, keys, value);
}, initialResult);
}

export default unflatten;
1 change: 1 addition & 0 deletions src/types/arrays.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type NonEmptyArray<TargetArray> = [TargetArray, ...TargetArray[]];
2 changes: 2 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './strings';
export * from './arrays';
7 changes: 7 additions & 0 deletions src/types/strings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type OnlyFirstCharacter<TargetString extends string> =
TargetString extends `${infer $TFirstChar}${string}` ? $TFirstChar : string;

export type Character<TargetString extends string> =
TargetString extends TargetString & OnlyFirstCharacter<TargetString>
? TargetString & OnlyFirstCharacter<TargetString>
: string & { length: 1 };

0 comments on commit 478a6da

Please sign in to comment.