mirror of
https://github.com/toss/es-toolkit.git
synced 2024-11-27 14:57:44 +03:00
feat(omit): Add compatibility version of omit
This commit is contained in:
parent
0edff25215
commit
1a5e9c8e64
@ -26,3 +26,15 @@ const obj = { a: 1, b: 2, c: 3 };
|
||||
const result = omit(obj, ['b', 'c']);
|
||||
// 結果は次のようになります { a: 1 }
|
||||
```
|
||||
|
||||
## Lodashとの互換性
|
||||
|
||||
`es-toolkit/compat`から`omit`関数をインポートすると、深いパスを省略することができます。
|
||||
|
||||
```typescript
|
||||
import { omit } from 'es-toolkit/compat';
|
||||
|
||||
const obj = { a: { b: { c: 1 } }, d: { e: 2 }, f: { g: 3 }, 'f.g': 4 };
|
||||
const result = omit(obj, ['a.b.c', 'f.g']);
|
||||
// result will be { a: { b: {} }, d: { e: 2 }, f: { g: 3 } }
|
||||
```
|
||||
|
@ -26,3 +26,15 @@ const obj = { a: 1, b: 2, c: 3 };
|
||||
const result = omit(obj, ['b', 'c']);
|
||||
// 결과는 다음과 같아요 { a: 1 }
|
||||
```
|
||||
|
||||
## Lodash와 호환성
|
||||
|
||||
`es-toolkit/compat`에서 `omit` 함수를 가져오면, 깊은 경로를 제외할 수 있어요.
|
||||
|
||||
```typescript
|
||||
import { omit } from 'es-toolkit/compat';
|
||||
|
||||
const obj = { a: { b: { c: 1 } }, d: { e: 2 }, f: { g: 3 }, 'f.g': 4 };
|
||||
const result = omit(obj, ['a.b.c', 'f.g']);
|
||||
// result will be { a: { b: {} }, d: { e: 2 }, f: { g: 3 } }
|
||||
```
|
||||
|
@ -27,3 +27,15 @@ const obj = { a: 1, b: 2, c: 3 };
|
||||
const result = omit(obj, ['b', 'c']);
|
||||
// result will be { a: 1 }
|
||||
```
|
||||
|
||||
## Compatibility with Lodash
|
||||
|
||||
The `omit` function from `es-toolkit/compat` allows you to exclude deep properties from an object.
|
||||
|
||||
```typescript
|
||||
import { omit } from 'es-toolkit/compat';
|
||||
|
||||
const obj = { a: { b: { c: 1 } }, d: { e: 2 }, f: { g: 3 }, 'f.g': 4 };
|
||||
const result = omit(obj, ['a.b.c', 'f.g']);
|
||||
// result will be { a: { b: {} }, d: { e: 2 }, f: { g: 3 } }
|
||||
```
|
||||
|
@ -26,3 +26,15 @@ const obj = { a: 1, b: 2, c: 3 };
|
||||
const result = omit(obj, ['b', 'c']);
|
||||
// result 将会是 { a: 1 }
|
||||
```
|
||||
|
||||
## 与 Lodash 的兼容性
|
||||
|
||||
`es-toolkit/compat` 中的 `omit` 函数可以省略深层路径的属性。
|
||||
|
||||
```typescript
|
||||
import { omit } from 'es-toolkit/compat';
|
||||
|
||||
const obj = { a: { b: { c: 1 } }, d: { e: 2 }, f: { g: 3 }, 'f.g': 4 };
|
||||
const result = omit(obj, ['a.b.c', 'f.g']);
|
||||
// result will be { a: { b: {} }, d: { e: 2 }, f: { g: 3 } }
|
||||
```
|
||||
|
@ -55,6 +55,7 @@ export { rearg } from './function/rearg.ts';
|
||||
export { get } from './object/get.ts';
|
||||
export { set } from './object/set.ts';
|
||||
export { pick } from './object/pick.ts';
|
||||
export { omit } from './object/omit.ts';
|
||||
export { has } from './object/has.ts';
|
||||
export { property } from './object/property.ts';
|
||||
export { mapKeys } from './object/mapKeys.ts';
|
||||
|
84
src/compat/object/omit.spec.ts
Normal file
84
src/compat/object/omit.spec.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { omit } from './omit';
|
||||
import { toArgs } from '../_internal/toArgs';
|
||||
import { objectProto } from '../_internal/objectProto';
|
||||
import { stringProto } from '../_internal/stringProto';
|
||||
|
||||
describe('omit', () => {
|
||||
it('should omit deep properties', () => {
|
||||
const obj = { a: { b: { c: 1 } }, d: { e: 2 }, f: { g: 3 }, 'f.g': 4 };
|
||||
const result = omit(obj, ['a.b.c', 'f.g']);
|
||||
expect(result).toEqual({ a: { b: {} }, d: { e: 2 }, f: { g: 3 } });
|
||||
});
|
||||
|
||||
const args = toArgs(['a', 'c']);
|
||||
const object = { a: 1, b: 2, c: 3, d: 4 };
|
||||
const nested = { a: 1, b: { c: 2, d: 3 } };
|
||||
|
||||
it('should flatten `paths`', () => {
|
||||
expect(omit(object, 'a', 'c')).toEqual({ b: 2, d: 4 });
|
||||
expect(omit(object, ['a', 'd'], 'c')).toEqual({ b: 2 });
|
||||
});
|
||||
|
||||
it('should support deep paths', () => {
|
||||
expect(omit(nested, 'b.c')).toEqual({ a: 1, b: { d: 3 } });
|
||||
});
|
||||
|
||||
it('should support path arrays', () => {
|
||||
const object = { 'a.b': 1, a: { b: 2 } };
|
||||
const actual = omit(object, [['a.b']]);
|
||||
|
||||
expect(actual).toEqual({ a: { b: 2 } });
|
||||
});
|
||||
|
||||
it('should omit a key over a path', () => {
|
||||
const object = { 'a.b': 1, a: { b: 2 } };
|
||||
|
||||
['a.b', ['a.b']].forEach(path => {
|
||||
expect(omit(object, path)).toEqual({ a: { b: 2 } });
|
||||
});
|
||||
});
|
||||
|
||||
it('should coerce `paths` to strings', () => {
|
||||
expect(omit({ 0: 'a' }, 0)).toEqual({});
|
||||
});
|
||||
|
||||
it('should return an empty object when `object` is nullish', () => {
|
||||
[null, undefined].forEach(value => {
|
||||
objectProto.a = 1;
|
||||
const actual = omit(value, 'valueOf');
|
||||
delete objectProto.a;
|
||||
expect(actual).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
// Manipulating prototypes is an anti-pattern
|
||||
it.skip('should work with a primitive `object`', () => {
|
||||
stringProto.a = 1;
|
||||
stringProto.b = 2;
|
||||
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
expect(omit('', 'b').a).toEqual(1);
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
expect(omit('', 'b').b).not.toEqual(2);
|
||||
|
||||
delete stringProto.a;
|
||||
delete stringProto.b;
|
||||
});
|
||||
|
||||
it('should work with `arguments` object `paths`', () => {
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
expect(omit(object, args)).toEqual({ b: 2, d: 4 });
|
||||
});
|
||||
|
||||
it('should not mutate `object`', () => {
|
||||
['a', ['a'], 'a.b', ['a.b']].forEach(path => {
|
||||
const object = { a: { b: 2 } };
|
||||
omit(object, path);
|
||||
expect(object).toEqual({ a: { b: 2 } });
|
||||
});
|
||||
});
|
||||
});
|
93
src/compat/object/omit.ts
Normal file
93
src/compat/object/omit.ts
Normal file
@ -0,0 +1,93 @@
|
||||
import { cloneDeep } from '../../object/cloneDeep.ts';
|
||||
import { unset } from './unset.ts';
|
||||
|
||||
/**
|
||||
* Creates a new object with specified keys omitted.
|
||||
*
|
||||
* This function takes an object and an array of keys, and returns a new object that
|
||||
* excludes the properties corresponding to the specified keys.
|
||||
*
|
||||
* @template T - The type of object.
|
||||
* @template K - The type of keys in object.
|
||||
* @param {T} obj - The object to omit keys from.
|
||||
* @param {K[]} keys - An array of keys to be omitted from the object.
|
||||
* @returns {Omit<T, K>} A new object with the specified keys omitted.
|
||||
*
|
||||
* @example
|
||||
* const obj = { a: 1, b: 2, c: 3 };
|
||||
* const result = omit(obj, ['b', 'c']);
|
||||
* // result will be { a: 1 }
|
||||
*/
|
||||
export function omit<T extends Record<string, any>, K extends keyof T>(obj: T, keys: readonly K[]): Omit<T, K>;
|
||||
|
||||
/**
|
||||
* Creates a new object with specified keys omitted.
|
||||
*
|
||||
* This function takes an object and a variable number of keys, and returns a new object that
|
||||
* excludes the properties corresponding to the specified keys.
|
||||
*
|
||||
* Deep keys can be specified for keys.
|
||||
*
|
||||
* @template T - The type of object.
|
||||
* @param {T} obj - The object to omit keys from.
|
||||
* @param {...(PropertyKey | PropertyKey[] | PropertyKey[][]} keys - A variable number of keys to be omitted from the object.
|
||||
* @returns {Partial<T>} A new object with the specified keys omitted.
|
||||
*/
|
||||
export function omit<T extends {}>(
|
||||
obj: T | null | undefined,
|
||||
...keys: Array<PropertyKey | readonly PropertyKey[] | readonly (readonly PropertyKey[])[]>
|
||||
): Partial<T>;
|
||||
|
||||
/**
|
||||
* Creates a new object with specified keys omitted.
|
||||
*
|
||||
* This function takes an object and a variable number of keys, and returns a new object that
|
||||
* excludes the properties corresponding to the specified keys. Note that keys can be deep.
|
||||
*
|
||||
* Deep keys can be specified for keys.
|
||||
*
|
||||
* @template T - The type of object.
|
||||
* @param {T} obj - The object to omit keys from.
|
||||
* @param {...(PropertyKey | PropertyKey[] | PropertyKey[][])} keysArr - A variable number of keys to be omitted from the object.
|
||||
* @returns {Partial<T>} A new object with the specified keys omitted.
|
||||
*/
|
||||
export function omit<T extends {}>(
|
||||
obj: T | null | undefined,
|
||||
...keysArr: Array<PropertyKey | readonly PropertyKey[] | readonly (readonly PropertyKey[])[]>
|
||||
): Partial<T> {
|
||||
if (obj == null) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const result = cloneDeep(obj);
|
||||
|
||||
for (let i = 0; i < keysArr.length; i++) {
|
||||
let keys = keysArr[i];
|
||||
|
||||
switch (typeof keys) {
|
||||
case 'object': {
|
||||
if (!Array.isArray(keys)) {
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
keys = Array.from(keys) as PropertyKey[];
|
||||
}
|
||||
|
||||
for (let j = 0; j < keys.length; j++) {
|
||||
const key = keys[j];
|
||||
|
||||
unset(result, key);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'string':
|
||||
case 'symbol':
|
||||
case 'number': {
|
||||
unset(result, keys);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
Loading…
Reference in New Issue
Block a user