From 6c9c0f11a548a1ed216de98c7cfcd92e8234029a Mon Sep 17 00:00:00 2001 From: ssi02014 Date: Wed, 12 Jun 2024 20:46:34 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20invert=20=EB=AA=85=ED=99=95=ED=95=9C?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EC=B6=94=EB=A1=A0=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=B8=20=ED=83=80=EC=9E=85=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/docs/utils/object/invert.md | 34 +++++++++++++++---- packages/utils/src/object/invert/index.ts | 30 +++++++++++----- .../utils/src/object/invert/invert.spec.ts | 27 +++++++++++++-- 3 files changed, 74 insertions(+), 17 deletions(-) diff --git a/docs/docs/utils/object/invert.md b/docs/docs/utils/object/invert.md index fe5998552..a30f7afb5 100644 --- a/docs/docs/utils/object/invert.md +++ b/docs/docs/utils/object/invert.md @@ -11,10 +11,14 @@ ## Interface ```ts title="typescript" -const invert: ( - obj: Record, - keyTransformer?: (value: any) => PropertyKey -) => Record; +const invert: < + K extends PropertyKey, + V, + TK extends PropertyKey = V extends PropertyKey ? V : PropertyKey +>( + obj: Record, + keyTransformer?: (value: V) => TK +) => Record; ``` ## Usage @@ -24,7 +28,9 @@ import { invert } from '@modern-kit/utils'; const obj = { a: 1, b: 2, c: 3 }; -invert(obj); // { 1: 'a', 2: 'b', 3: 'c' }; +invert(obj); +// value: { 1: 'a', 2: 'b', 3: 'c' }; +// type: Record ``` ### KeyTransformer @@ -35,5 +41,21 @@ const obj = { a: [1, 2, 3], b: [4, 5, 6] }; invert(obj, (value) => { return JSON.stringify(value); -}); // { '[1,2,3]': 'a', '[4,5,6]': 'b' } +}); +// value: { '[1,2,3]': 'a', '[4,5,6]': 'b' } +// type: Record +``` + +### const assertion +```ts title="typescript" +import { invert } from '@modern-kit/utils'; + +const obj = { + a: { name: 'foo' }, + b: { name: 'bar' }, +} as const; + +invert(obj, (value) => value.name); +// value: { foo: 'a', bar: 'b' } +// type: Record<"foo" | "bar", "a" | "b"> ``` \ No newline at end of file diff --git a/packages/utils/src/object/invert/index.ts b/packages/utils/src/object/invert/index.ts index ae17e35ad..56c059de1 100644 --- a/packages/utils/src/object/invert/index.ts +++ b/packages/utils/src/object/invert/index.ts @@ -1,15 +1,27 @@ -import { identity } from '../../common'; +import { hasProperty } from '../../validator'; -export const invert = ( - obj: Record, - keyTransformer: (value: any) => PropertyKey = identity +const defaultKeyTransformer = (value: V) => { + return value as unknown as TK; +}; + +export const invert = < + K extends PropertyKey, + V, + TK extends PropertyKey = V extends PropertyKey ? V : PropertyKey +>( + obj: Record, + keyTransformer: (value: V) => TK = defaultKeyTransformer ) => { - const invertedObj: Record = {}; + const invertedObj = {} as Record; + + for (const key in obj) { + if (hasProperty(obj, key)) { + const value = obj[key]; + const transformedKey = keyTransformer(value); - Object.keys(obj).forEach((key) => { - const value = obj[key]; - invertedObj[keyTransformer(value)] = key; - }); + invertedObj[transformedKey] = key; + } + } return invertedObj; }; diff --git a/packages/utils/src/object/invert/invert.spec.ts b/packages/utils/src/object/invert/invert.spec.ts index 40b4f6d6e..6c700d2ae 100644 --- a/packages/utils/src/object/invert/invert.spec.ts +++ b/packages/utils/src/object/invert/invert.spec.ts @@ -6,14 +6,37 @@ describe('invert', () => { const result = invert(obj); expect(result).toEqual({ 1: 'a', 2: 'b', 3: 'c' }); + expectTypeOf(result).toEqualTypeOf>(); }); - it('should use the keyTransformer if provided', () => { + it('should use the keyTransformer if provided(1)', () => { const obj = { a: 1, b: 2, c: 3 }; - const keyTransformer = (value: number) => `key_${value}`; + const keyTransformer = (value: number): `key_${number}` => `key_${value}`; const result = invert(obj, keyTransformer); expect(result).toEqual({ key_1: 'a', key_2: 'b', key_3: 'c' }); + expectTypeOf(result).toEqualTypeOf< + Record<`key_${number}`, 'a' | 'b' | 'c'> + >(); + }); + + it('should use the keyTransformer if provided(2)', () => { + const obj = { a: [1, 2, 3], b: [1, 2, 3], c: [1, 2, 3] } as const; + const result = invert(obj, (value) => value[0]); + + expect(result).toEqual({ 1: 'c' }); + expectTypeOf(result).toEqualTypeOf>(); + }); + + it('should use the keyTransformer if provided(3)', () => { + const obj = { + a: { name: 'foo' }, + b: { name: 'bar' }, + } as const; + const result = invert(obj, (value) => value.name); + + expect(result).toEqual({ foo: 'a', bar: 'b' }); + expectTypeOf(result).toEqualTypeOf>(); }); it('should handle an empty object', () => { From 72d8a138d5704c226a16202c82eecf90ac9dfc17 Mon Sep 17 00:00:00 2001 From: ssi02014 Date: Wed, 12 Jun 2024 21:29:39 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20invert=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/docs/utils/object/invert.md | 2 +- packages/utils/src/object/invert/index.ts | 17 +++++++---------- packages/utils/src/object/invert/invert.spec.ts | 10 ++++++++++ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/docs/docs/utils/object/invert.md b/docs/docs/utils/object/invert.md index a30f7afb5..249b0b522 100644 --- a/docs/docs/utils/object/invert.md +++ b/docs/docs/utils/object/invert.md @@ -18,7 +18,7 @@ const invert: < >( obj: Record, keyTransformer?: (value: V) => TK -) => Record; +) => Record>; ``` ## Usage diff --git a/packages/utils/src/object/invert/index.ts b/packages/utils/src/object/invert/index.ts index 56c059de1..3ee674c88 100644 --- a/packages/utils/src/object/invert/index.ts +++ b/packages/utils/src/object/invert/index.ts @@ -1,5 +1,3 @@ -import { hasProperty } from '../../validator'; - const defaultKeyTransformer = (value: V) => { return value as unknown as TK; }; @@ -12,16 +10,15 @@ export const invert = < obj: Record, keyTransformer: (value: V) => TK = defaultKeyTransformer ) => { - const invertedObj = {} as Record; + const invertedObj = {} as Record>; + const keys = Object.keys(obj) as Exclude[]; - for (const key in obj) { - if (hasProperty(obj, key)) { - const value = obj[key]; - const transformedKey = keyTransformer(value); + keys.forEach((key) => { + const value = obj[key]; + const transformedKey = keyTransformer(value); - invertedObj[transformedKey] = key; - } - } + invertedObj[transformedKey] = key; + }); return invertedObj; }; diff --git a/packages/utils/src/object/invert/invert.spec.ts b/packages/utils/src/object/invert/invert.spec.ts index 6c700d2ae..a451e481a 100644 --- a/packages/utils/src/object/invert/invert.spec.ts +++ b/packages/utils/src/object/invert/invert.spec.ts @@ -39,6 +39,16 @@ describe('invert', () => { expectTypeOf(result).toEqualTypeOf>(); }); + it('should exclude keys that contain symbols.', () => { + const symbol = Symbol(1); + + const obj = { [symbol]: 1, foo: 2 } as const; + const result = invert(obj); + + expect(result).toEqual({ 2: 'foo' }); + expectTypeOf(result).toEqualTypeOf>(); + }); + it('should handle an empty object', () => { const obj = {}; const result = invert(obj);