feat(property): Add property

This commit is contained in:
raon0211 2024-07-25 12:04:32 +09:00
parent 13c7c7f611
commit 0e0329ac91
11 changed files with 255 additions and 1 deletions

View File

@ -0,0 +1,15 @@
import { property as propertyToolkit } from 'es-toolkit/compat';
import { property as propertyLodash } from 'lodash';
import { bench, describe } from 'vitest';
describe('property', () => {
bench('es-toolkit/property', () => {
const getValue = propertyToolkit('a.b');
getValue({ 'a.b': 1, a: { b: 1 } });
})
bench('lodash/property', () => {
const getValue = propertyLodash('a.b');
getValue({ 'a.b': 1, a: { b: 1 } });
})
})

View File

@ -150,6 +150,7 @@ function sidebar(): DefaultTheme.Sidebar {
{ text: 'pickBy', link: '/reference/object/pickBy' },
{ text: 'get (compat)', link: '/reference/compat/object/get' },
{ text: 'set (compat)', link: '/reference/compat/object/set' },
{ text: 'property (compat)', link: '/reference/compat/object/property' },
],
},
{

View File

@ -161,6 +161,7 @@ function sidebar(): DefaultTheme.Sidebar {
{ text: 'pickBy', link: '/ko/reference/object/pickBy' },
{ text: 'get (호환성)', link: '/ko/reference/compat/object/get' },
{ text: 'set (호환성)', link: '/ko/reference/compat/object/set' },
{ text: 'property (호환성)', link: '/ko/reference/compat/object/property' },
],
},
{

View File

@ -145,6 +145,7 @@ function sidebar(): DefaultTheme.Sidebar {
{ text: 'pickBy', link: '/zh_hans/reference/object/pickBy' },
{ text: 'get (兼容性)', link: '/zh_hans/reference/compat/object/get' },
{ text: 'set (兼容性)', link: '/zh_hans/reference/compat/object/set' },
{ text: 'property (兼容性)', link: '/zh_hans/reference/compat/object/property' },
],
},
{

View File

@ -6,7 +6,7 @@
객체에서 주어진 경로에 있는 값을 가져와요. 그 값이 `undefined` 라면, 기본값을 반환해요.
## Signature
## 인터페이스
```typescript
function get<T extends object, K extends keyof T>(object: T, path: K | [K]): T[K];

View File

@ -0,0 +1,35 @@
# property
::: info
이 함수는 [lodash와 완전히 호환](../../../compatibility.md)돼요. `es-toolkit/compat` 라이브러리에서 쓸 수 있어요.
:::
객체에서 주어진 경로에 있는 값을 가져오는 함수를 만들어요. 값을 가져오기 위해서는 [`get`](./get.md) 함수를 사용해요.
## 인터페이스
```typescript
function property(path: PropertyKey | readonly PropertyKey[]): (object: unknown) => any
```
### 파라미터
- `path` (`string` or `number` or `symbol` or `Array<string | number | symbol>`): 프로퍼티를 가져올 경로.
### 반환 값
(`(object: unknown) => any`): 객체에서 주어진 경로에 있는 값을 가져오는 함수.
### 예시
```typescript
import { property } from 'es-toolkit/compat';
const getObjectValue = property('a.b.c');
const result = getObjectValue({ a: { b: { c: 3 } } });
console.log(result); // => 3
const getObjectValue = property(['a', 'b', 'c']);
const result = getObjectValue({ a: { b: { c: 3 } } });
console.log(result); // => 3
```

View File

@ -0,0 +1,36 @@
# property
::: info
This function is fully compatible with lodash. You can find it in our [compatibility library](../../../compatibility.md), `es-toolkit/compat`.
:::
Creates a function that returns the value at a given path of an object.
It leverages the [`get`](./get.md) functions to obtain the value.
## Signature
```typescript
function property(path: PropertyKey | readonly PropertyKey[]): (object: unknown) => any
```
### Parameters
- `path` (`string` or `number` or `symbol` or `Array<string | number | symbol>`): The path of the property to get.
### Returns
(`(object: unknown) => any`): A new function that takes an object and returns the value at the specified path.
### Examples
```typescript
import { property } from 'es-toolkit/compat';
const getObjectValue = property('a.b.c');
const result = getObjectValue({ a: { b: { c: 3 } } });
console.log(result); // => 3
const getObjectValue = property(['a', 'b', 'c']);
const result = getObjectValue({ a: { b: { c: 3 } } });
console.log(result); // => 3
```

View File

@ -0,0 +1,35 @@
# property
::: info
此函数与 lodash 完全兼容。您可以在我们的[兼容性库](../../../compatibility.md)中找到它,`es-toolkit/compat`。
:::
`property` 函数创建一个新函数,用于从对象中获取指定路径的值。它利用 [`get`](./get.md) 函数来获取值。
## 签名
```typescript
function property(path: PropertyKey | readonly PropertyKey[]): (object: unknown) => any
```
### 参数
- `path` (`string` | `number` | `symbol` | `Array<string | number | symbol>`): 要获取的属性路径。
### 返回值
- `(object: unknown) => any`: 一个函数,接收一个对象并返回指定路径的值。
### 示例
```typescript
import { property } from 'es-toolkit/compat';
const getObjectValue = property('a.b.c');
const result = getObjectValue({ a: { b: { c: 3 } } });
console.log(result); // => 3
const getObjectValue = property(['a', 'b', 'c']);
const result = getObjectValue({ a: { b: { c: 3 } } });
console.log(result); // => 3
```

View File

@ -33,6 +33,7 @@ export { head as first } from '../index.ts';
export { get } from './object/get.ts';
export { set } from './object/set.ts';
export { property } from './object/property.ts';
export { isPlainObject } from './predicate/isPlainObject.ts';
export { isArray } from './predicate/isArray.ts';

View File

@ -0,0 +1,106 @@
import { describe, expect, it } from 'vitest';
import { property } from './property';
import { noop } from '../../function/noop';
describe('property', () => {
it('should create a function that plucks a property value of a given object', () => {
const object = { a: 1 };
['a', ['a']].forEach((path) => {
const prop = property(path);
expect(prop.length).toBe(1);
expect(prop(object)).toBe(1);
})
});
it('should pluck deep property values', () => {
const object = { a: { b: 2 } };
['a.b', ['a', 'b']].forEach((path) => {
const prop = property(path);
expect(prop(object)).toBe(2);
});
});
it('should pluck inherited property values', () => {
function Foo() { }
Foo.prototype.a = 1;
['a', ['a']].forEach((path) => {
const prop = property(path);
expect(prop(
// eslint-disable-next-line
// @ts-ignore
new Foo()
)).toBe(1);
});
});
it('should work with a non-string `path`', () => {
const array = [1, 2, 3];
[1, [1]].forEach((path) => {
const prop = property(path);
expect(prop(array)).toBe(2);
});
});
it('should preserve the sign of `0`', () => {
const object = { '-0': 'a', 0: 'b' };
const props = [-0, Object(-0), 0, Object(0)];
const actual = props.map((key) => {
const prop = property(key);
return prop(object);
});
expect(actual).toEqual(['a', 'a', 'b', 'b']);
});
it('should pluck a key over a path', () => {
const object = { 'a.b': 1, a: { b: 2 } };
['a.b', ['a.b']].forEach((path) => {
const prop = property(path);
expect(prop(object)).toBe(1);
});
});
it('should return `undefined` when `object` is nullish', () => {
const values = [null, undefined];
const expected = values.map(noop);
['constructor', ['constructor']].forEach((path) => {
const prop = property(path);
const actual = values.map((value) => prop(value))
expect(actual).toEqual(expected);
});
});
it('should return `undefined` for deep paths when `object` is nullish', () => {
const values = [null, undefined];
const expected = values.map(noop);
['constructor.prototype.valueOf', ['constructor', 'prototype', 'valueOf']]
.forEach(
(path) => {
const prop = property(path);
const actual = values.map((value, index) => prop(value));
expect(actual).toEqual(expected);
},
);
});
it('should return `undefined` if parts of `path` are missing', () => {
const object = {};
['a', 'a[1].b.c', ['a'], ['a', '1', 'b', 'c']].forEach((path) => {
const prop = property(path);
expect(prop(object)).toBe(undefined);
});
});
});

View File

@ -0,0 +1,23 @@
import { get } from "./get.ts";
/**
* Creates a function that returns the value at a given path of an object.
*
* @param {PropertyKey | readonly PropertyKey[]} path - The path of the property to get.
* @returns {(object: unknown) => any} - Returns a new function that takes an object and returns the value at the specified path.
*
* @example
* const getObjectValue = property('a.b.c');
* const result = getObjectValue({ a: { b: { c: 3 } } });
* console.log(result); // => 3
*
* @example
* const getObjectValue = property(['a', 'b', 'c']);
* const result = getObjectValue({ a: { b: { c: 3 } } });
* console.log(result); // => 3
*/
export function property(path: PropertyKey | readonly PropertyKey[]): (object: unknown) => any {
return function (object: unknown) {
return get(object, path);
}
}