feat(every): Ensure compatibility with lodash

This commit is contained in:
Sojin Park 2024-09-28 22:48:32 +09:00
parent b0daa7377d
commit efe7932200
13 changed files with 836 additions and 242 deletions

View File

@ -0,0 +1,119 @@
# every
::: info
この関数は互換性のために `es-toolkit/compat` からのみインポートできます。代替可能なネイティブ JavaScript API があるか、まだ十分に最適化されていないためです。
`es-toolkit/compat` からこの関数をインポートすると、[lodash と完全に同じように動作](../../../compatibility.md)します。
:::
配列やオブジェクトのすべての要素が指定された条件を満たすかどうかを確認します。
条件は複数の方法で指定できます。
- **検査関数**: 各要素に対して検査する関数を実行します。すべての要素が `true` を返す場合、結果は `true` になります。
- **部分オブジェクト**: 与えられたオブジェクトとすべてのプロパティが一致する場合にのみ `true` を返します。
- **プロパティ-値ペア**: 該当プロパティに対してすべての要素が値が一致する場合に `true` を返します。
- **プロパティ名**: 該当プロパティに対してすべての要素が真と評価される値を持つ場合に `true` を返します。
## インターフェース
```typescript
function every<T>(arr: T[], doesMatch: (item: T, index: number, arr: T[]) => unknown): boolean;
function every<T>(arr: T[], doesMatch: Partial<T>): boolean;
function every<T>(arr: T[], doesMatch: [keyof T, unknown]): boolean;
function every<T>(arr: T[], doesMatch: string): boolean;
function every<T extends Record<string, unknown>>(
object: T,
doesMatch: (item: T[keyof T], index: number, object: T) => unknown
): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: Partial<T[keyof T]>): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: [keyof T, unknown]): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: string): boolean;
```
### パラメータ
- `arr` (`T[]`) または `object` (`T`): 検索する配列またはオブジェクト。
- `doesMatch`:
- 配列の場合:
- **検査関数** (`(item: T, index: number, arr: T[]) => unknown`): 条件を満たすかどうかを確認する関数。すべての要素が条件を満たす場合、結果は `true` になります。
- **部分オブジェクト** (`Partial<T>`): 与えられた部分オブジェクトのプロパティと値に一致する場合、すべての要素が条件を満たす必要があります。
- **プロパティ-値ペア** (`[keyof T, unknown]`): 最初が一致させるプロパティ、2番目が一致させる値を表すタプル。すべての要素がこの条件を満たす場合、結果は `true` になります。
- **プロパティ名** (`string`): 指定されたプロパティがすべての要素に対して真と評価される場合、結果は `true` になります。
- オブジェクトの場合:
- **検査関数** (`(item: T[keyof T], index: number, object: T) => unknown`): 条件を満たすかどうかを確認する関数。すべての要素が条件を満たす場合、結果は `true` になります。
- **部分値** (`Partial<T[keyof T]>`): 与えられた部分値に一致する場合、すべての要素が条件を満たす必要があります。
- **プロパティ-値ペア** (`[keyof T, unknown]`): 最初が一致させるプロパティ、2番目が一致させる値を表すタプル。すべての要素がこの条件を満たす場合、結果は `true` になります。
- **プロパティ名** (`string`): 指定されたプロパティがすべての要素に対して真と評価される場合、結果は `true` になります。
### 戻り値
(`boolean`): 与えられた条件を満たすすべての要素がある場合は `true`、そうでない場合は `false` を返します。
## 例
### 配列の場合
```typescript
import { every } from 'es-toolkit/compat';
// 検査関数を使う場合
const items = [1, 2, 3, 4, 5];
const result = every(items, item => item > 0);
console.log(result); // true
// 部分オブジェクトを使う場合
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, { name: 'Bob' });
console.log(result); // false
// プロパティ-値ペアを使う場合
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, ['name', 'Alice']);
console.log(result); // false
// プロパティ名を使う場合
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, 'name');
console.log(result); // false
```
### オブジェクトの場合
```typescript
import { every } from 'es-toolkit/compat';
// 検査関数を使う場合
const obj = { a: 1, b: 2, c: 3 };
const result = every(obj, item => item > 0);
console.log(result); // true
// 部分オブジェクトを使う場合
const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
const result = every(obj, { name: 'Bob' });
console.log(result); // false
// プロパティ-値ペアを使う場合
const items = { alice: { id: 1, name: 'Alice' }, bob: { id: 2, name: 'Bob' } };
const result = every(items, ['name', 'Alice']);
console.log(result); // false
// プロパティ名を使う場合
const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
const result = every(obj, 'name');
console.log(result); // false
```

View File

@ -1,44 +0,0 @@
# every
컬렉션의 모든 요소가 주어진 조건을 만족하는지 확인해요.
이 함수는 배열, 객체, 문자열을 처리할 수 있으며, 컬렉션의 모든 요소가 조건을 만족하면 `true`, 그렇지 않으면 `false`를 반환해요.
만약 컬렉션이 `null` 또는 `undefined`일 경우에는 `true`를 반환해요.
빈 배열 `[]`, 빈 문자열 `''`, 빈 객체 `{}`는 기본적으로 `true`를 반환해요.
## 인터페이스
```typescript
function every<T>(
collection: T[] | { [key: string]: T } | string | null | undefined,
predicate: (value: T, indexOrKey: number | string) => boolean
): boolean;
```
### 파라미터
- `collection` (`T[] | { [key: string]: T } | string | null | undefined`): 조건을 확인할 배열, 객체, 문자열 또는 `null`/`undefined`.
- `predicate` (`(value: T, indexOrKey: number | string) => boolean`): 각 요소를 테스트할 함수에요. 현재 요소의 값과 인덱스(또는 객체의 키)를 받아요.
### 반환 값
(`boolean`): 컬렉션의 모든 요소가 조건을 만족하거나 컬렉션이 비어있을 때는 `true`, 그렇지 않으면 `false` 를 반환해요.
## Examples
```typescript
import { every } from 'es-toolkit/collection';
const numbers = [1, 2, 3];
const allPositive = every(numbers, (value) => value > 0);
console.log(allPositive); // true
const str = 'abc';
const allLowerCase = every(str, (char) => /[a-z]/.test(char));
console.log(allLowerCase); // true
const obj = { a: 1, b: 2, c: 3 };
const allGreaterThanZero = every(obj, (value) => value > 0);
console.log(allGreaterThanZero); // true
```

View File

@ -0,0 +1,119 @@
# every
::: info
이 함수는 호환성을 위한 `es-toolkit/compat` 에서만 가져올 수 있어요. 대체할 수 있는 네이티브 JavaScript API가 있거나, 아직 충분히 최적화되지 않았기 때문이에요.
`es-toolkit/compat`에서 이 함수를 가져오면, [lodash와 완전히 똑같이 동작](../../../compatibility.md)해요.
:::
배열이나 객체의 모든 값이 주어진 조건에 맞는지 반환해요.
조건은 여러 방법들로 명시할 수 있어요.
- **검사 함수**: 각각의 요소에 대해서 검사하는 함수를 실행해요. 모든 요소가 `true`를 반환해야 결과가 `true`가 돼요.
- **부분 객체**: 주어진 객체와 모든 프로퍼티가 일치하는 경우에만 `true`를 반환해요.
- **프로퍼티-값 쌍**: 해당 프로퍼티에 대해서 모든 요소가 값이 일치해야 `true`를 반환해요.
- **프로퍼티 이름**: 해당 프로퍼티에 대해서 모든 요소가 참으로 평가되는 값을 가져야 `true`를 반환해요.
## 인터페이스
```typescript
function every<T>(arr: T[], doesMatch: (item: T, index: number, arr: T[]) => unknown): boolean;
function every<T>(arr: T[], doesMatch: Partial<T>): boolean;
function every<T>(arr: T[], doesMatch: [keyof T, unknown]): boolean;
function every<T>(arr: T[], doesMatch: string): boolean;
function every<T extends Record<string, unknown>>(
object: T,
doesMatch: (item: T[keyof T], index: number, object: T) => unknown
): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: Partial<T[keyof T]>): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: [keyof T, unknown]): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: string): boolean;
```
### 파라미터
- `arr` (`T[]`) 또는 `object` (`T`): 검색할 배열이나 객체.
- `doesMatch`:
- 배열의 경우:
- **검사 함수** (`(item: T, index: number, arr: T[]) => unknown`): 모든 요소가 조건을 만족하는지 확인하는 함수.
- **부분 객체** (`Partial<T>`): 모든 요소가 주어진 부분 객체의 프로퍼티와 값에 일치해야 `true`를 반환하는 객체.
- **프로퍼티-값 쌍** (`[keyof T, unknown]`): 첫 번째가 일치시킬 프로퍼티, 두 번째가 일치시킬 값을 나타내는 튜플로, 모든 요소가 이 조건을 만족해야 `true`를 반환.
- **프로퍼티 이름** (`string`): 모든 요소가 해당 프로퍼티에 대해 참으로 평가되는 값을 가져야 `true`를 반환.
- 객체의 경우:
- **검사 함수** (`(item: T[keyof T], index: number, object: T) => unknown`): 모든 요소가 조건을 만족하는지 확인하는 함수.
- **Partial value** (`Partial<T[keyof T]>`): 모든 요소가 주어진 부분 값에 일치해야 `true`를 반환하는 객체.
- **Property-value pair** (`[keyof T, unknown]`): 첫 번째가 일치시킬 프로퍼티, 두 번째가 일치시킬 값을 나타내는 튜플로, 모든 요소가 이 조건을 만족해야 `true`를 반환.
- **Property name** (`string`): 모든 요소가 해당 프로퍼티에 대해 참으로 평가되는 값을 가져야 `true`를 반환.
### 반환 값
(`boolean`): 주어진 조건을 만족하는 모든 요소가 있을 경우 `true`, 그렇지 않으면 `false`를 반환.
## 예시
### 배열의 경우
```typescript
import { every } from 'es-toolkit/compat';
// 검사 함수를 쓰는 경우
const items = [1, 2, 3, 4, 5];
const result = every(items, item => item > 0);
console.log(result); // true
// 부분 객체를 쓰는 경우
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, { name: 'Bob' });
console.log(result); // false
// 프로퍼티-값 쌍을 쓰는 경우
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, ['name', 'Alice']);
console.log(result); // false
// 프로퍼티 이름을 쓰는 경우
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, 'name');
console.log(result); // false
```
### 객체의 경우
```typescript
import { every } from 'es-toolkit/compat';
// 검사 함수를 쓰는 경우
const obj = { a: 1, b: 2, c: 3 };
const result = every(obj, item => item > 0);
console.log(result); // true
// 부분 객체를 쓰는 경우
const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
const result = every(obj, { name: 'Bob' });
console.log(result); // false
// 프로퍼티-값 쌍을 쓰는 경우
const items = { alice: { id: 1, name: 'Alice' }, bob: { id: 2, name: 'Bob' } };
const result = every(items, ['name', 'Alice']);
console.log(result); // false
// 프로퍼티 이름을 쓰는 경우
const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
const result = every(obj, 'name');
console.log(result); // false
```

View File

@ -1,44 +0,0 @@
# every
Checks if all elements in a collection pass the provided predicate.
This function can handle arrays, objects, and strings.
It returns true if all elements or characters in the collection satisfy the predicate function, or if the collection is null, undefined, empty, or has no elements.
Note: Empty arrays `[]`, empty strings `''`, and empty objects `{}` return `true` by default.
## Signature
```typescript
function every<T>(
collection: T[] | { [key: string]: T } | string | null | undefined,
predicate: (value: T, indexOrKey: number | string) => boolean
): boolean;
```
### Parameters
- `collection` (`T[] | { [key: string]: T } | string | null | undefined`): The collection to check, which can be an array, object, string, or `null`/`undefined`.
- `predicate` (`(value: T, indexOrKey: number | string) => boolean`): A function to test each element. It receives the current element's value and index (or key in the case of objects).
### Returns
(`boolean`): Returns `true` if all elements pass the predicate, or if the collection is empty, `null`, or `undefined`. Returns `false` if any element fails the predicate.
## Examples
```typescript
import { every } from 'es-toolkit/collection';
const numbers = [1, 2, 3];
const allPositive = every(numbers, (value) => value > 0);
console.log(allPositive); // true
const str = 'abc';
const allLowerCase = every(str, (char) => /[a-z]/.test(char));
console.log(allLowerCase); // true
const obj = { a: 1, b: 2, c: 3 };
const allGreaterThanZero = every(obj, (value) => value > 0);
console.log(allGreaterThanZero); // true
```

View File

@ -0,0 +1,119 @@
# every
::: info
This function is only available in `es-toolkit/compat` for compatibility reasons. It either has alternative native JavaScript APIs or isnt fully optimized yet.
When imported from `es-toolkit/compat`, it behaves exactly like lodash and provides the same functionalities, as detailed [here](../../../compatibility.md).
:::
Checks if all elements in an array or object meet the specified condition.
You can specify the condition in several ways:
- **Predicate function**: If you provide a predicate function, the function will be applied to each item. If the predicate function returns `true` for all items, the result will be `true`.
- **Partial object**: If you provide a partial object, the function will return `true` if all items match the properties of the partial object.
- **Property-value pair**: If you provide a property-value pair, the function will return `true` if all items match the property and value from the pair.
- **Property name**: If you provide a property name, the function will return `true` if all items have the specified property with a truthy value.
## Signature
```typescript
function every<T>(arr: T[], doesMatch: (item: T, index: number, arr: T[]) => unknown): boolean;
function every<T>(arr: T[], doesMatch: Partial<T>): boolean;
function every<T>(arr: T[], doesMatch: [keyof T, unknown]): boolean;
function every<T>(arr: T[], doesMatch: string): boolean;
function every<T extends Record<string, unknown>>(
object: T,
doesMatch: (item: T[keyof T], index: number, object: T) => unknown
): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: Partial<T[keyof T]>): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: [keyof T, unknown]): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: string): boolean;
```
### Parameters
- `arr` (`T[]`) or `object` (`T`): The array or object to search through.
- `doesMatch`:
- For the first `every` overload with arrays:
- **Predicate function** (`(item: T, index: number, arr: T[]) => unknown`): A function that takes an item, its index, and the array, and returns a truthy value if the item matches the criteria.
- **Partial object** (`Partial<T>`): A partial object that specifies the properties to match.
- **Property-value pair** (`[keyof T, unknown]`): An array where the first element is the property key and the second element is the value to match.
- **Property name** (`string`): The name of the property to check for a truthy value.
- For the `every` overloads with objects:
- **Predicate function** (`(item: T[keyof T], index: number, object: T) => unknown`): A function that takes an item, its key, and the object, and returns a truthy value if the item matches the criteria.
- **Partial value** (`Partial<T[keyof T]>`): A partial value to match against the values of the object.
- **Property-value pair** (`[keyof T, unknown]`): An array where the first element is the property key and the second element is the value to match.
- **Property name** (`string`): The name of the property to check for a truthy value.
### Returns
(`boolean`): Returns `true` if all items match the specified condition, or `false` if any item does not match.
## Examples
### Arrays
```typescript
import { every } from 'es-toolkit/compat';
// Using a predicate function
const items = [1, 2, 3, 4, 5];
const result = every(items, item => item > 0);
console.log(result); // true
// Using a partial object
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, { name: 'Bob' });
console.log(result); // false
// Using a property-value pair
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, ['name', 'Alice']);
console.log(result); // false
// Using a property name
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, 'name');
console.log(result); // false
```
### Objects
```typescript
import { every } from 'es-toolkit/compat';
// Using a predicate function
const obj = { a: 1, b: 2, c: 3 };
const result = every(obj, item => item > 0);
console.log(result); // true
// Using a partial value
const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
const result = every(obj, { name: 'Bob' });
console.log(result); // false
// Using a property-value pair
const items = { alice: { id: 1, name: 'Alice' }, bob: { id: 2, name: 'Bob' } };
const result = every(items, ['name', 'Alice']);
console.log(result); // false
// Using a property name
const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
const result = every(obj, 'name');
console.log(result); // false
```

View File

@ -0,0 +1,120 @@
# find
::: info
出于兼容性原因,此函数仅在 `es-toolkit/compat` 中提供。它可能具有替代的原生 JavaScript API或者尚未完全优化。
`es-toolkit/compat` 导入时,它的行为与 lodash 完全一致,并提供相同的功能,详情请见 [这里](../../../compatibility.md)。
:::
检查数组或对象的所有元素是否满足指定条件。
您可以通过以下几种方式指定条件:
- **检查函数**:如果提供一个检查函数,该函数将应用于每一项。所有项都返回 `true` 时,结果为 `true`
- **部分对象**:如果提供一个部分对象,该函数将返回 `true`,如果所有项匹配部分对象的属性。
- **属性-值对**:如果提供一个属性-值对,该函数将返回 `true`,如果所有项匹配该属性和值。
- **属性名称**:如果提供一个属性名称,该函数将返回 `true`,如果所有项具有指定属性且其值为真。
## 签名
```typescript
function every<T>(arr: T[], doesMatch: (item: T, index: number, arr: T[]) => unknown): boolean;
function every<T>(arr: T[], doesMatch: Partial<T>): boolean;
function every<T>(arr: T[], doesMatch: [keyof T, unknown]): boolean;
function every<T>(arr: T[], doesMatch: string): boolean;
function every<T extends Record<string, unknown>>(
object: T,
doesMatch: (item: T[keyof T], index: number, object: T) => unknown
): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: Partial<T[keyof T]>): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: [keyof T, unknown]): boolean;
function every<T extends Record<string, unknown>>(object: T, doesMatch: string): boolean;
```
### 参数
- `arr` (`T[]`) 或 `object` (`T`): 要搜索的数组或对象。
- `doesMatch`:
- 对于数组的 `every` 重载:
- **检查函数** (`(item: T, index: number, arr: T[]) => unknown`): 一个函数,接受项、其索引和数组,如果所有项都符合条件则返回 `true`
- **部分对象** (`Partial<T>`): 指定要匹配的属性的部分对象,所有项必须匹配这些属性。
- **属性-值对** (`[keyof T, unknown]`): 一个数组,第一个元素是属性键,第二个元素是要匹配的值,所有项必须匹配该属性和值。
- **属性名称** (`string`): 要检查其真值的属性名称,所有项必须具有该属性且其值为真。
- 对于对象的 `every` 重载:
- **检查函数** (`(item: T[keyof T], index: number, object: T) => unknown`): 一个函数,接受项、其键和对象,如果所有项都符合条件则返回 `true`
- **部分值** (`Partial<T[keyof T]>`): 用于与对象的值进行匹配的部分值,所有项必须匹配这些值。
- **属性-值对** (`[keyof T, unknown]`): 一个数组,第一个元素是属性键,第二个元素是要匹配的值,所有项必须匹配该属性和值。
- **属性名称** (`string`): 要检查其真值的属性名称,所有项必须具有该属性且其值为真。
### 返回
(`boolean`): 如果所有项都满足指定条件,则返回 `true`,否则返回 `false`
## 示例
### 数组
```typescript
import { every } from 'es-toolkit/compat';
// 使用谓词函数
const items = [1, 2, 3, 4, 5];
const result = every(items, item => item > 0);
console.log(result); // true
// 使用部分对象
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, { name: 'Bob' });
console.log(result); // false
// 使用属性-值对
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, ['name', 'Alice']);
console.log(result); // false
// 使用属性名称
const items = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const result = every(items, 'name');
console.log(result); // false
```
### 对象
```typescript
import { every } from 'es-toolkit/compat';
// 使用谓词函数
const obj = { a: 1, b: 2, c: 3 };
const result = every(obj, item => item > 0);
console.log(result); // true
// 使用部分对象
const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
const result = every(obj, { name: 'Bob' });
console.log(result); // false
// 使用属性-值对
const items = { alice: { id: 1, name: 'Alice' }, bob: { id: 2, name: 'Bob' } };
const result = every(items, ['name', 'Alice']);
console.log(result); // false
// 使用属性名称
const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
const result = every(obj, 'name');
console.log(result); // false
```

View File

@ -1,77 +0,0 @@
import { describe, expect, it } from 'vitest';
import { every } from './every';
describe('every', () => {
it('should return true for array with all elements passing predicate', () => {
const arr = [1, 2, 3, 4];
const result = every(arr, n => n > 0);
expect(result).toBe(true);
});
it('should return false for array when an element does not pass predicate', () => {
const arr = [1, 2, 3, -4];
const result = every(arr, n => n > 0);
expect(result).toBe(false);
});
it('should return true for empty array', () => {
const result = every([], () => false);
expect(result).toBe(true);
});
it('should return true for object with all values passing predicate', () => {
const obj = { a: 1, b: 2, c: 3 };
const result = every(obj, value => value > 0);
expect(result).toBe(true);
});
it('should return false for object when a value does not pass predicate', () => {
const obj = { a: 1, b: -2, c: 3 };
const result = every(obj, value => value > 0);
expect(result).toBe(false);
});
it('should return true for empty object', () => {
const result = every({}, () => false);
expect(result).toBe(true);
});
it('should return true for string where all characters pass predicate', () => {
const str = 'hello';
const result = every(str, char => char !== ' ');
expect(result).toBe(true);
});
it('should return false for string where a character does not pass predicate', () => {
const str = 'hello world';
const result = every(str, char => char !== ' ');
expect(result).toBe(false);
});
it('should return true for empty string', () => {
const result = every('', () => false);
expect(result).toBe(true);
});
it('should return true for null', () => {
const result = every(null, () => false);
expect(result).toBe(true);
});
it('should return true for undefined', () => {
const result = every(undefined, () => false);
expect(result).toBe(true);
});
it('should correctly handle indices for arrays', () => {
const arr = [1, 2, 3];
const result = every(arr, (n, index) => index < 3);
expect(result).toBe(true);
});
it('should correctly handle keys for objects', () => {
const obj = { a: 1, b: 2, c: 3 };
const result = every(obj, (value, key) => ['a', 'b', 'c'].includes(key));
expect(result).toBe(true);
});
});

View File

@ -1,75 +0,0 @@
/**
* Checks if all elements in a collection pass the predicate.
*
* Returns `true` if all elements in an array, object, or string satisfy the predicate,
* or if the collection is `null` or `undefined`.
*
* Note: Empty arrays `[]`, empty strings `''`, and empty objects `{}` return `true` by default.
*
* @template T The type of elements in the collection.
* @param {T[] | { [key: string]: T } | string | null | undefined} collection - The collection to check.
* @param {(value: T, indexOrKey: number | string) => boolean} predicate - The function to test each element.
* @returns {boolean} `true` if all elements pass the predicate, `false` otherwise.
*
* @example
* every([1, 2, 3], (value) => value > 0); // true
* @example
* every('abc', (char) => /[a-z]/.test(char)); // true
* @example
* every({ a: 1, b: 2 }, (value) => value > 0); // true
*/
export function every<T>(collection: T[] | null | undefined, predicate: (value: T, index: number) => boolean): boolean;
export function every<T>(
collection: { [key: string]: T } | null | undefined,
predicate: (value: T, key: string) => boolean
): boolean;
export function every(
collection: string | null | undefined,
predicate: (value: string, index: number) => boolean
): boolean;
export function every<T>(
collection: T[] | { [key: string]: T } | string | null | undefined,
predicate: (value: any, index: any) => boolean
): boolean {
if (collection == null) {
return true;
}
if (Array.isArray(collection)) {
if (collection.length === 0) {
return true;
}
for (let i = 0; i < collection.length; i++) {
if (!predicate(collection[i], i)) {
return false;
}
}
return true;
}
if (typeof collection === 'string') {
if (collection.length === 0) {
return true;
}
for (let i = 0; i < collection.length; i++) {
if (!predicate(collection[i], i)) {
return false;
}
}
return true;
}
const keys = Object.keys(collection);
if (keys.length === 0) {
return true;
}
for (const key of keys) {
if (!predicate(collection[key], key)) {
return false;
}
}
return true;
}

View File

@ -9,7 +9,6 @@ export { drop } from './drop.ts';
export { dropRight } from './dropRight.ts';
export { dropRightWhile } from './dropRightWhile.ts';
export { dropWhile } from './dropWhile.ts';
export { every } from './every.ts';
export { fill } from './fill.ts';
export { flatMap } from './flatMap.ts';
export { flatMapDeep } from './flatMapDeep.ts';

View File

@ -0,0 +1,134 @@
import { describe, expect, it } from 'vitest';
import { every } from './every';
import { identity } from '../_internal/identity';
import { empties } from '../_internal/empties';
import { stubTrue } from '../_internal/stubTrue';
import { stubFalse } from '../_internal/stubFalse';
describe('every', () => {
it('should return true for array with all elements passing predicate', () => {
const arr = [1, 2, 3, 4];
const result = every(arr, n => n > 0);
expect(result).toBe(true);
});
it('should return false for array when an element does not pass predicate', () => {
const arr = [1, 2, 3, -4];
const result = every(arr, n => n > 0);
expect(result).toBe(false);
});
it('should return true for empty array', () => {
const result = every([], () => false);
expect(result).toBe(true);
});
it('should return true for object with all values passing predicate', () => {
const obj = { a: 1, b: 2, c: 3 };
const result = every(obj, value => value > 0);
expect(result).toBe(true);
});
it('should return false for object when a value does not pass predicate', () => {
const obj = { a: 1, b: -2, c: 3 };
const result = every(obj, value => value > 0);
expect(result).toBe(false);
});
it('should return true for empty object', () => {
const result = every({}, () => false);
expect(result).toBe(true);
});
it('should correctly handle indices for arrays', () => {
const arr = [1, 2, 3];
const result = every(arr, (n, index) => index < 3);
expect(result).toBe(true);
});
it('should correctly handle keys for objects', () => {
const obj = { a: 1, b: 2, c: 3 };
const result = every(obj, (value, key) => ['a', 'b', 'c'].includes(key as any));
expect(result).toBe(true);
});
it('should return `true` if `predicate` returns truthy for all elements', () => {
expect(every([true, 1, 'a'], identity)).toBe(true);
});
it('should return `true` for empty collections', () => {
const expected = empties.map(stubTrue);
const actual = empties.map(value => {
try {
return every(value, identity);
} catch (e) {}
});
expect(actual).toEqual(expected);
});
it('should return `false` as soon as `predicate` returns falsey', () => {
let count = 0;
expect(
every([true, null, true], value => {
count++;
return value;
})
).toEqual(false);
expect(count).toBe(2);
});
it('should work with collections of `undefined` values (test in IE < 9)', () => {
expect(every([undefined, undefined, undefined], identity)).toBe(false);
});
it('should use `_.identity` when `predicate` is nullish', () => {
const values = [, null, undefined];
let expected = values.map(stubFalse);
let actual = values.map((value, index) => {
const array = [0];
// eslint-disable-next-line
// @ts-ignore
return index ? every(array, value) : every(array);
});
expect(actual).toEqual(expected);
expected = values.map(stubTrue);
actual = values.map((value, index) => {
const array = [1];
// eslint-disable-next-line
// @ts-ignore
return index ? every(array, value) : every(array);
});
expect(actual).toEqual(expected);
});
it('should work with `_.property` shorthands', () => {
const objects = [
{ a: 0, b: 1 },
{ a: 1, b: 2 },
];
expect(every(objects, 'a')).toBe(false);
expect(every(objects, 'b')).toBe(true);
});
it('should work with `_.matches` shorthands', () => {
const objects = [
{ a: 0, b: 0 },
{ a: 0, b: 1 },
];
expect(every(objects, { a: 0 })).toBe(true);
expect(every(objects, { b: 1 })).toBe(false);
});
it('should work as an iteratee for methods like `_.map`', () => {
const actual = [[1]].map(every);
expect(actual).toEqual([true]);
});
});

223
src/compat/array/every.ts Normal file
View File

@ -0,0 +1,223 @@
import { identity } from '../_internal/identity.ts';
import { property } from '../object/property.ts';
import { matches } from '../predicate/matches.ts';
import { matchesProperty } from '../predicate/matchesProperty.ts';
/**
* Checks if all elements in an array are truthy.
*
* @template T
* @param {T[]} arr - The array to check through.
* @returns {boolean} - `true` if all elements are truthy, or `false` if at least one element is falsy.
*
* @example
* const items = [1, 2, 3, 4];
* const result = every(items);
* console.log(result); // true
*
* const itemsWithFalsy = [1, 0, 3, 4];
* const resultWithFalsy = every(itemsWithFalsy);
* console.log(resultWithFalsy); // false
*/
export function every<T>(arr: readonly T[]): boolean;
/**
* Checks if every item in an array matches the given predicate function.
*
* @template T
* @param {T[]} arr - The array to check through.
* @param {(item: T, index: number, arr: T[]) => unknown} doesMatch - A function that takes an item, its index, and the array, and returns a truthy value if the item matches the criteria.
* @returns {boolean} - `true` if every item matches the predicate, or `false` if at least one item does not match.
*
* @example
* // Using a predicate function
* const items = [1, 2, 3, 4, 5];
* const result = every(items, (item) => item > 0);
* console.log(result); // true
*/
export function every<T>(arr: readonly T[], doesMatch: (item: T, index: number, arr: readonly T[]) => unknown): boolean;
/**
* Checks if every item in an array matches the given partial object.
*
* @template T
* @param {T[]} arr - The array to check through.
* @param {Partial<T>} doesMatch - A partial object that specifies the properties to match.
* @returns {boolean} - `true` if every item matches the partial object, or `false` if at least one item does not match.
*
* @example
* // Using a partial object
* const items = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
* const result = every(items, { name: 'Bob' });
* console.log(result); // false
*/
export function every<T>(arr: readonly T[], doesMatch: Partial<T>): boolean;
/**
* Checks if every item in an array matches a property with a specific value.
*
* @template T
* @param {readonly T[]} arr - The array to check through.
* @param {[keyof T, unknown]} doesMatchProperty - An array where the first element is the property key and the second element is the value to match.
* @returns {boolean} - `true` if every item has the specified property value, or `false` if at least one item does not match.
*
* @example
* // Using a property-value pair
* const items = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
* const result = every(items, ['name', 'Alice']);
* console.log(result); // false
*/
export function every<T>(arr: readonly T[], doesMatchProperty: [keyof T, unknown]): boolean;
/**
* Checks if every item in an array has a specific property, where the property name is provided as a string.
*
* @template T
* @param {readonly T[]} arr - The array to check through.
* @param {string} propertyToCheck - The property name to check.
* @returns {boolean} - `true` if every item has the specified property, or `false` if at least one item does not match.
*
* @example
* // Using a property name
* const items = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
* const result = every(items, 'name');
* console.log(result); // true
*/
export function every<T>(arr: readonly T[], propertyToCheck: string): boolean;
/**
* Checks if every item in an object matches the given predicate function.
*
* @template T
* @param {T extends Record<string, unknown> ? T : never} object - The object to check through.
* @param {(item: T[keyof T], index: keyof T, arr: T) => unknown} doesMatch - A function that takes an item, its key, and the object, and returns a truthy value if the item matches the criteria.
* @returns {boolean} - `true` if every property value matches the predicate, or `false` if at least one does not match.
*
* @example
* // Using a predicate function
* const obj = { a: 1, b: 2, c: 3 };
* const result = every(obj, (item) => item > 0);
* console.log(result); // true
*/
export function every<T extends Record<string, unknown>>(
object: T,
doesMatch: (item: T[keyof T], index: keyof T, object: T) => unknown
): boolean;
/**
* Checks if every item in an object matches the given partial value.
*
* @template T
* @param {T extends Record<string, unknown> ? T : never} object - The object to check through.
* @param {Partial<T[keyof T]>} doesMatch - A partial value to match against the values of the object.
* @returns {boolean} - `true` if every property value matches the partial value, or `false` if at least one does not match.
*
* @example
* // Using a partial value
* const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
* const result = every(obj, { name: 'Bob' });
* console.log(result); // false
*/
export function every<T extends Record<string, unknown>>(object: T, doesMatch: Partial<T[keyof T]>): boolean;
/**
* Checks if every item in an object matches a property with a specific value.
*
* @template T
* @param {readonly T[]} object - The object to check through.
* @param {[keyof T, unknown]} doesMatchProperty - An array where the first element is the property key and the second element is the value to match.
* @returns {boolean} - `true` if every item has the specified property value, or `false` if at least one item does not match.
*
* @example
* // Using a property-value pair
* const items = { alice: { id: 1, name: 'Alice' }, bob: { id: 2, name: 'Bob' } };
* const result = every(items, ['name', 'Alice']);
* console.log(result); // false
*/
export function every<T extends Record<string, unknown>>(object: T, doesMatchProperty: [keyof T, unknown]): boolean;
/**
* Checks if every item in an object has a specific property, where the property name is provided as a string.
*
* @template T
* @param {T extends Record<string, unknown> ? T : never} object - The object to check through.
* @param {string} propertyToCheck - The property name to check.
* @returns {boolean} - `true` if every property value has the specified property, or `false` if at least one does not match.
*
* @example
* // Using a property name
* const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
* const result = every(obj, 'name');
* console.log(result); // true
*/
export function every<T extends Record<string, unknown>>(object: T, propertyToCheck: string): boolean;
/**
* Checks if every item in an object has a specific property, where the property name is provided as a string.
*
* @template T
* @param {T extends Record<string, unknown> ? T : never} object - The object to check through.
* @param {readonly T[] | Record<any, any>} source - The source array or object to check through.
* @param {((item: T, index: number, arr: any) => unknown) | Partial<T> | [keyof T, unknown] | string} doesMatch - The criteria to match. It can be a function, a partial object, a key-value pair, or a property name.
* @param {string} propertyToCheck - The property name to check.
* @returns {boolean} - `true` if every property value has the specified property, or `false` if at least one does not match.
*
* @example
* // Using a property name
* const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
* const result = every(obj, 'name');
* console.log(result); // true
*/
export function every<T>(
source: readonly T[] | Record<any, any>,
doesMatch?: ((item: T, index: number, arr: any) => unknown) | Partial<T> | [keyof T, unknown] | string
): boolean {
if (!source) {
source = [];
}
let values = source;
if (!Array.isArray(source)) {
values = Object.values(source);
}
if (!doesMatch) {
doesMatch = identity;
}
switch (typeof doesMatch) {
case 'function': {
if (!Array.isArray(source)) {
const entries: any[] = Object.entries(source);
for (let i = 0; i < entries.length; i++) {
const entry = entries[i];
const key = entry[0];
const value = entry[1];
if (!doesMatch(value, key, source)) {
return false;
}
}
return true;
}
return values.every(doesMatch);
}
case 'object': {
if (Array.isArray(doesMatch) && doesMatch.length === 2) {
const key = doesMatch[0];
const value = doesMatch[1];
return values.every(matchesProperty(key, value));
} else {
return values.every(matches(doesMatch));
}
}
case 'string': {
return values.every(property(doesMatch));
}
}
}

View File

@ -85,7 +85,7 @@ export function find<T>(arr: readonly T[], propertyToCheck: string): T | undefin
*/
export function find<T extends Record<string, unknown>>(
object: T,
doesMatch: (item: T[keyof T], index: number, object: T) => unknown
doesMatch: (item: T[keyof T], index: keyof T, object: T) => unknown
): T | undefined;
/**

View File

@ -30,6 +30,7 @@ export { concat } from './array/concat.ts';
export { difference } from './array/difference.ts';
export { drop } from './array/drop.ts';
export { dropWhile } from './array/dropWhile.ts';
export { every } from './array/every.ts';
export { fill } from './array/fill.ts';
export { find } from './array/find.ts';
export { findIndex } from './array/findIndex.ts';