feat(isLength): Add isLength (#245)

* feat(predicate, compat, isLength): impl isLength

Signed-off-by: sunrabbit123 <qudwls185@naver.com>

* docs: change compatibility mark

Signed-off-by: sunrabbit123 <qudwls185@naver.com>

* test(isLength, compat): add test case link

Signed-off-by: sunrabbit123 <qudwls185@naver.com>

* docs(predicate, isLength): add route path on vitepress

Signed-off-by: sunrabbit123 <qudwls185@naver.com>

* Update docs/ko/reference/predicate/isLength.md

---------

Signed-off-by: sunrabbit123 <qudwls185@naver.com>
Co-authored-by: Sojin Park <raon0211@gmail.com>
Co-authored-by: Sojin Park <raon0211@toss.im>
This commit is contained in:
오병진 2024-07-19 19:18:20 -07:00 committed by GitHub
parent 701e82300b
commit caedf69aed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 168 additions and 3 deletions

View File

@ -0,0 +1,34 @@
import { bench, describe } from 'vitest';
import { isLength as isLengthToolkit } from 'es-toolkit';
import { isLength as isLengthLodash } from 'lodash';
describe('isLength', () => {
bench('es-toolkit/isLength', () => {
isLengthToolkit(100);
isLengthToolkit(0);
isLengthToolkit(-1);
isLengthToolkit(1.5);
isLengthToolkit(Number.MAX_SAFE_INTEGER);
isLengthToolkit(Number.MAX_SAFE_INTEGER + 1);
isLengthToolkit('100');
isLengthToolkit(true);
isLengthToolkit(null);
isLengthToolkit(undefined);
isLengthToolkit({});
isLengthToolkit([]);
});
bench('lodash/isLength', () => {
isLengthLodash(100);
isLengthLodash(0);
isLengthLodash(-1);
isLengthLodash(1.5);
isLengthLodash(Number.MAX_SAFE_INTEGER);
isLengthLodash(Number.MAX_SAFE_INTEGER + 1);
isLengthLodash('100');
isLengthLodash(true);
isLengthLodash(null);
isLengthLodash(undefined);
isLengthLodash({});
isLengthLodash([]);
});
});

View File

@ -151,6 +151,7 @@ function sidebar(): DefaultTheme.Sidebar {
text: 'Predicates',
items: [
{ text: 'isEqual', link: '/reference/predicate/isEqual' },
{ text: 'isLength', link: '/reference/predicate/isLength' },
{ text: 'isPlainObject', link: '/reference/predicate/isPlainObject' },
{ text: 'isNil', link: '/reference/predicate/isNil' },
{ text: 'isNotNil', link: '/reference/predicate/isNotNil' },

View File

@ -162,6 +162,7 @@ function sidebar(): DefaultTheme.Sidebar {
text: '타입 가드',
items: [
{ text: 'isEqual', link: '/ko/reference/predicate/isEqual' },
{ text: 'isLength', link: '/ko/reference/predicate/isLength' },
{ text: 'isPlainObject', link: '/ko/reference/predicate/isPlainObject' },
{ text: 'isNil', link: '/ko/reference/predicate/isNil' },
{ text: 'isNotNil', link: '/ko/reference/predicate/isNotNil' },

View File

@ -209,7 +209,7 @@ Even if a feature is marked "in review," it might already be under review to ens
| [isFinite](https://lodash.com/docs/4.17.15#isFinite) | ❌ |
| [isFunction](https://lodash.com/docs/4.17.15#isFunction) | ❌ |
| [isInteger](https://lodash.com/docs/4.17.15#isInteger) | ❌ |
| [isLength](https://lodash.com/docs/4.17.15#isLength) | |
| [isLength](https://lodash.com/docs/4.17.15#isLength) | |
| [isMap](https://lodash.com/docs/4.17.15#isMap) | ❌ |
| [isMatch](https://lodash.com/docs/4.17.15#isMatch) | ❌ |
| [isMatchWith](https://lodash.com/docs/4.17.15#isMatchWith) | ❌ |

View File

@ -210,7 +210,7 @@ chunk([1, 2, 3, 4], 0);
| [isFinite](https://lodash.com/docs/4.17.15#isFinite) | ❌ |
| [isFunction](https://lodash.com/docs/4.17.15#isFunction) | ❌ |
| [isInteger](https://lodash.com/docs/4.17.15#isInteger) | ❌ |
| [isLength](https://lodash.com/docs/4.17.15#isLength) | |
| [isLength](https://lodash.com/docs/4.17.15#isLength) | |
| [isMap](https://lodash.com/docs/4.17.15#isMap) | ❌ |
| [isMatch](https://lodash.com/docs/4.17.15#isMatch) | ❌ |
| [isMatchWith](https://lodash.com/docs/4.17.15#isMatchWith) | ❌ |

View File

@ -0,0 +1,41 @@
# isLength
주어진 값이 유효한 길이인지 확인해요.
유효한 길이란, `0` 이상 `Number.MAX_SAFE_INTEGER` 미만의 정수를 말해요.
TypeScript의 타입 가드로 사용할 수 있어요. 파라미터로 주어진 값의 타입을 `number`로 좁혀요.
## Signature
```typescript
function isLength(value: unknown): value is number;
```
### Parameters
- `value` (`unknown`): 유효한 길이인지 확인할 값
### Returns
(`value is number`): 값이 유효한 길이면 `true`, 아니면 `false`.
## Examples
```typescript
import { isLength } from 'es-toolkit/predicate';
const value1 = 0;
const value2 = 42;
const value3 = -1;
const value4 = 1.5;
const value5 = Number.MAX_SAFE_INTEGER;
const value6 = Number.MAX_SAFE_INTEGER + 1;
console.log(isLength(value1)); // true
console.log(isLength(value2)); // true
console.log(isLength(value3)); // false
console.log(isLength(value4)); // false
console.log(isLength(value5)); // true
console.log(isLength(value6)); // false
```

View File

@ -0,0 +1,41 @@
# isLength
Checks if a given value is a valid length.
This function tests whether the provided value is of type `number`, is a non-negative integer, and is less than or equal to JavaScript's maximum safe integer (`Number.MAX_SAFE_INTEGER`). It returns `true` if the value is a valid length, and `false` otherwise.
This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to a valid length (`number`).
## Signature
```typescript
function isLength(value: unknown): value is number;
```
### Parameters
- `value` (`unknown`): The value to check if it is a valid length.
### Returns
(`value is number`): Returns `true` if the value is a valid length, otherwise `false`.
## Examples
```typescript
import { isLength } from 'es-toolkit/predicate';
const value1 = 0;
const value2 = 42;
const value3 = -1;
const value4 = 1.5;
const value5 = Number.MAX_SAFE_INTEGER;
const value6 = Number.MAX_SAFE_INTEGER + 1;
console.log(isLength(value1)); // true
console.log(isLength(value2)); // true
console.log(isLength(value3)); // false
console.log(isLength(value4)); // false
console.log(isLength(value5)); // true
console.log(isLength(value6)); // false
```

View File

@ -0,0 +1,23 @@
import { isLength } from '../index';
import { describe, expect, it } from 'vitest';
/**
* @see https://github.com/lodash/lodash/blob/6a2cc1dfcf7634fea70d1bc5bd22db453df67b42/test/isLength.spec.js#L1
*/
describe('isLength', () => {
it('should return `true` for lengths', () => {
const values = [0, 3, Number.MAX_SAFE_INTEGER];
const expected = values.map(() => true);
const actual = values.map(isLength);
expect(actual).toEqual(expected);
});
it('should return `false` for non-lengths', () => {
const values = [-1, '1', 1.1, Number.MAX_SAFE_INTEGER + 1];
const expected = values.map(() => false);
const actual = values.map(isLength);
expect(actual).toEqual(expected);
});
});

View File

@ -3,4 +3,5 @@ export { isNil } from './isNil.ts';
export { isNotNil } from './isNotNil.ts';
export { isNull } from './isNull.ts';
export { isUndefined } from './isUndefined.ts';
export { isPlainObject } from './isPlainObject.ts';
export { isLength } from './isLength.ts';
export { isPlainObject } from './isPlainObject.ts';

View File

@ -0,0 +1,20 @@
import { isLength } from './isLength';
import { describe, expect, it } from 'vitest';
describe('isLength', () => {
it('should return `true` for lengths', () => {
const values = [0, 3, Number.MAX_SAFE_INTEGER];
const expected = values.map(() => true);
const actual = values.map(isLength);
expect(actual).toEqual(expected);
});
it('should return `false` for non-lengths', () => {
const values = [-1, '1', 1.1, Number.MAX_SAFE_INTEGER + 1];
const expected = values.map(() => false);
const actual = values.map(isLength);
expect(actual).toEqual(expected);
});
});

View File

@ -0,0 +1,3 @@
export function isLength(value: unknown): value is number {
return typeof value === 'number' && value > -1 && value % 1 === 0 && value <= Number.MAX_SAFE_INTEGER;
}