Skip to content

Commit

Permalink
feat(utils): contain 신규 유틸 함수 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
ssi02014 committed Jun 3, 2024
1 parent 5679d43 commit 91f7ba1
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/unlucky-rules-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@modern-kit/utils': minor
---

feat(utils): contain 신규 유틸 함수 추가 - @ssi02014
74 changes: 74 additions & 0 deletions docs/docs/utils/array/contain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# contain

첫 번째 인자로 넘긴 배열에 특정 요소가 포함되어 있는지 판단하는 유틸 함수입니다.

includes의 `as const`를 활용 했을 때, 타입이 호환되지 않은 요소가 포함되어 있는지 확인 할 때 타입 에러가 발생하는 문제점을 `some` 메서드를 활용해 개선하기 위한 함수입니다.

```ts title="typescript"
const arr = [1, 2, 3] as const

arr.includes(4); // '4' 형식의 인수는 '1 | 2 | 3' 형식의 매개 변수에 할당될 수 없습니다.
```

`some` 메서드를 통해 요소가 포함되어 있는지 판단 할 때 기본적으로 `Object.is` 메서드를 활용합니다. 단, 필요 시에 3번째 인자로 `comparator` 함수를 활용 할 수 있습니다.


## Code

[🔗 실제 구현 코드 확인](https://github.com/modern-agile-team/modern-kit/blob/main/packages/utils/src/array/contain/index.ts)

## Interface

```ts title="typescript"
const contain: <T>(
arr: readonly T[] | T[],
value: unknown,
comparator?: (x: any, y: any) => boolean // default: Object.is
) => value is T;
```

## Usage
### Default
```ts title="typescript"
import { contain } from '@modern-kit/utils';

const arr = [0, 1, 2, 3, NaN, {}];

contain(arr, 1); // true
contain(arr, NaN); // true

contain(arr, -0); // false
contain(arr, 4); // false
contain(arr, "3"); // false
contain(arr, {}); // false
```

### Comparator
```ts title="typescript"
const arr = [{ a: 1, b: 2 }];

contain(arr, { a: 1, c: 2 }, (x, y) => x.a === y.a); // true
contain(
arr,
{ a: 1, b: 2 },
(x, y) => JSON.stringify(x) === JSON.stringify(y)
); // true
```

### Narrowing types
```ts title="typescript"
const arr = [2, 3, 'foo'] as const;
const value = 'foo' as unknown;

if (contain(arr, value)) {
value; // 2 | 3 | 'foo'
} else {
value; // unknown
}
```

## Note
- [Object.is(en) - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
- [Object.is(ko) - MDN](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
- [동등 비교 및 동일성(en) - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness)
- [동등 비교 및 동일성(ko) - MDN](https://developer.mozilla.org/ko/docs/Web/JavaScript/Equality_comparisons_and_sameness#%EB%8F%99%EC%9D%BC_%EA%B0%92_%EC%A0%9C%EB%A1%9C_%EB%8F%99%EB%93%B1)
40 changes: 40 additions & 0 deletions packages/utils/src/array/contain/contain.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { contain } from '.';

describe('contain', () => {
it('should return true if the array contains the element, otherwise return false.', () => {
const arr = [0, 1, 2, 'foo', NaN, {}];

expect(contain(arr, 1)).toBeTruthy();
expect(contain(arr, 'foo')).toBeTruthy();
expect(contain(arr, NaN)).toBeTruthy();

expect(contain(arr, 4)).toBeFalsy();
expect(contain(arr, {})).toBeFalsy();
expect(contain(arr, -0)).toBeFalsy();
expect(contain(arr, '2')).toBeFalsy();
});

it('should determine inclusion based on the result of the comparator function if provided.', () => {
const arr = [{ a: 1, b: 2 }];

expect(contain(arr, { a: 1, c: 2 }, (x, y) => x.a === y.a)).toBeTruthy();
expect(
contain(
arr,
{ a: 1, b: 2 },
(x, y) => JSON.stringify(x) === JSON.stringify(y)
)
).toBeTruthy();
});

it('should perform type narrowing with conditional expressions.', () => {
const arr = [2, 3, 'foo'] as const;
const value = 'foo' as unknown;

if (contain(arr, value)) {
expectTypeOf(value).toEqualTypeOf<2 | 3 | 'foo'>();
} else {
expectTypeOf(value).toEqualTypeOf<unknown>();
}
});
});
7 changes: 7 additions & 0 deletions packages/utils/src/array/contain/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const contain = <T>(
arr: T[] | ReadonlyArray<T>,
value: unknown,
comparator: (x: any, y: any) => boolean = Object.is
): value is T => {
return arr.some((item) => comparator(item, value));
};
3 changes: 2 additions & 1 deletion packages/utils/src/array/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './chunk';
export * from './contain';
export * from './countOccurrencesInArray';
export * from './excludeElements';
export * from './chunk';

0 comments on commit 91f7ba1

Please sign in to comment.