Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions docs/ja/reference/object/sortKeys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# sortKeys

キーがソートされた新しいオブジェクトを作成します。

```typescript
const sorted = sortKeys(object, compare?);
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TypeScript snippet sortKeys(object, compare?) is not valid TypeScript syntax (the ? marker can’t be used in a call expression). Update the snippet to a valid call (e.g. sortKeys(object) and sortKeys(object, compare)).

Suggested change
const sorted = sortKeys(object, compare?);
const sorted = sortKeys(object, compare);

Copilot uses AI. Check for mistakes.
```

## 使い方

### `sortKeys(object, compare?)`

オブジェクトのキーを一定の順序にソートしたい場合に`sortKeys`を使用します。デフォルトではキーがアルファベット順にソートされるため、シリアライズ、比較、表示などの用途に便利です。

```typescript
import { sortKeys } from 'es-toolkit/object';

const sorted = sortKeys({ c: 3, a: 1, b: 2 });
// { a: 1, b: 2, c: 3 }
```

カスタム比較関数を渡して、異なるソート方式を使用することもできます。

```typescript
// 逆アルファベット順にソートします
const reversed = sortKeys({ a: 1, b: 2, c: 3 }, (a, b) => b.localeCompare(a));
// { c: 3, b: 2, a: 1 }
```

値はネストされたオブジェクトや配列を含め、そのまま保持されます。

```typescript
const obj = { z: [1, 2], a: { nested: true }, m: 'hello' };
const sorted = sortKeys(obj);
// { a: { nested: true }, m: 'hello', z: [1, 2] }
```

#### パラメータ

- `object` (`T`): キーをソートするオブジェクトです。
- `compare` (`(a: string, b: string) => number`, オプション): キーのソートに使用するカスタム比較関数です。デフォルトはアルファベット順です。

#### 戻り値

(`T`): キーがソートされた新しいオブジェクトを返します。
45 changes: 45 additions & 0 deletions docs/ko/reference/object/sortKeys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# sortKeys

키가 정렬된 새로운 객체를 생성해요.

```typescript
const sorted = sortKeys(object, compare?);
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TypeScript snippet sortKeys(object, compare?) is not valid TypeScript syntax (the ? marker can’t be used in a call expression). Update the snippet to a valid call (e.g. sortKeys(object) and sortKeys(object, compare)).

Suggested change
const sorted = sortKeys(object, compare?);
const sorted = sortKeys(object, compare);

Copilot uses AI. Check for mistakes.
```

## 사용법

### `sortKeys(object, compare?)`

객체의 키를 일정한 순서로 정렬하고 싶을 때 `sortKeys`를 사용하세요. 기본적으로 키가 알파벳순으로 정렬되어서, 직렬화, 비교, 표시 등의 용도에 유용해요.

```typescript
import { sortKeys } from 'es-toolkit/object';

const sorted = sortKeys({ c: 3, a: 1, b: 2 });
// { a: 1, b: 2, c: 3 }
```

커스텀 비교 함수를 전달해서 다른 정렬 방식을 사용할 수도 있어요.

```typescript
// 역 알파벳 순으로 정렬해요
const reversed = sortKeys({ a: 1, b: 2, c: 3 }, (a, b) => b.localeCompare(a));
// { c: 3, b: 2, a: 1 }
```

값은 중첩된 객체나 배열을 포함해서 그대로 유지돼요.

```typescript
const obj = { z: [1, 2], a: { nested: true }, m: 'hello' };
const sorted = sortKeys(obj);
// { a: { nested: true }, m: 'hello', z: [1, 2] }
```

#### 파라미터

- `object` (`T`): 키를 정렬할 객체예요.
- `compare` (`(a: string, b: string) => number`, 선택): 키 정렬에 사용할 커스텀 비교 함수예요. 기본값은 알파벳순이에요.

#### 반환 값

(`T`): 키가 정렬된 새로운 객체를 반환해요.
45 changes: 45 additions & 0 deletions docs/reference/object/sortKeys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# sortKeys

Creates a new object with the keys sorted.

```typescript
const sorted = sortKeys(object, compare?);
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TypeScript snippet sortKeys(object, compare?) is not valid TypeScript syntax (the ? marker can’t be used in a call expression). Update the snippet to a valid call (e.g. sortKeys(object) and sortKeys(object, compare)).

Suggested change
const sorted = sortKeys(object, compare?);
const sorted = sortKeys(object);

Copilot uses AI. Check for mistakes.
```

## Usage

### `sortKeys(object, compare?)`

Use `sortKeys` when you want to create a new object with its keys in a deterministic order. Keys are sorted alphabetically by default, which is useful for serialization, comparison, or display purposes.

```typescript
import { sortKeys } from 'es-toolkit/object';

const sorted = sortKeys({ c: 3, a: 1, b: 2 });
// { a: 1, b: 2, c: 3 }
```

You can also provide a custom compare function for different sorting behavior.

```typescript
// Sort in reverse alphabetical order
const reversed = sortKeys({ a: 1, b: 2, c: 3 }, (a, b) => b.localeCompare(a));
// { c: 3, b: 2, a: 1 }
```

Values are preserved as-is, including nested objects and arrays.

```typescript
const obj = { z: [1, 2], a: { nested: true }, m: 'hello' };
const sorted = sortKeys(obj);
// { a: { nested: true }, m: 'hello', z: [1, 2] }
```

#### Parameters

- `object` (`T`): The object to sort keys from.
- `compare` (`(a: string, b: string) => number`, optional): A custom compare function for sorting keys. Defaults to alphabetical order.

#### Returns

(`T`): A new object with the keys sorted.
45 changes: 45 additions & 0 deletions docs/zh_hans/reference/object/sortKeys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# sortKeys

创建一个键已排序的新对象。

```typescript
const sorted = sortKeys(object, compare?);
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码片段 sortKeys(object, compare?) 不是合法的 TypeScript 调用写法(? 只能用于类型/参数声明,不能用于调用表达式)。建议改为合法的调用示例(例如 sortKeys(object) / sortKeys(object, compare))。

Suggested change
const sorted = sortKeys(object, compare?);
const sorted = sortKeys(object);

Copilot uses AI. Check for mistakes.
```

## 用法

### `sortKeys(object, compare?)`

当您想要以确定性顺序排列对象的键时,可以使用 `sortKeys`。默认情况下,键按字母顺序排序,这对于序列化、比较或显示等场景很有用。

```typescript
import { sortKeys } from 'es-toolkit/object';

const sorted = sortKeys({ c: 3, a: 1, b: 2 });
// { a: 1, b: 2, c: 3 }
```

您也可以提供自定义比较函数来实现不同的排序方式。

```typescript
// 按字母逆序排序
const reversed = sortKeys({ a: 1, b: 2, c: 3 }, (a, b) => b.localeCompare(a));
// { c: 3, b: 2, a: 1 }
```

值会原样保留,包括嵌套对象和数组。

```typescript
const obj = { z: [1, 2], a: { nested: true }, m: 'hello' };
const sorted = sortKeys(obj);
// { a: { nested: true }, m: 'hello', z: [1, 2] }
```

#### 参数

- `object` (`T`): 要排序键的对象。
- `compare` (`(a: string, b: string) => number`, 可选): 用于排序键的自定义比较函数。默认为字母顺序。

#### 返回值

(`T`): 返回一个键已排序的新对象。
1 change: 1 addition & 0 deletions src/object/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export { omit } from './omit.ts';
export { omitBy } from './omitBy.ts';
export { pick } from './pick.ts';
export { pickBy } from './pickBy.ts';
export { sortKeys } from './sortKeys.ts';
export { toCamelCaseKeys } from './toCamelCaseKeys.ts';
export { toMerged } from './toMerged.ts';
export { toSnakeCaseKeys } from './toSnakeCaseKeys.ts';
50 changes: 50 additions & 0 deletions src/object/sortKeys.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { describe, expect, it } from 'vitest';
import { sortKeys } from './sortKeys';

describe('sortKeys', () => {
it('should sort object keys alphabetically by default', () => {
const result = sortKeys({ c: 3, a: 1, b: 2 });
expect(Object.keys(result)).toEqual(['a', 'b', 'c']);
expect(result).toEqual({ a: 1, b: 2, c: 3 });
});

it('should sort keys with a custom compare function', () => {
const result = sortKeys({ a: 1, b: 2, c: 3 }, (a, b) => b.localeCompare(a));
expect(Object.keys(result)).toEqual(['c', 'b', 'a']);
});
Comment on lines +4 to +14
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no test covering objects that contain an own enumerable "__proto__" key. Given other object utilities explicitly guard against unsafe keys, add a test ensuring sortKeys does not mutate the returned object's prototype when sorting such inputs.

Copilot uses AI. Check for mistakes.

it('should return an empty object for empty input', () => {
const result = sortKeys({});
expect(result).toEqual({});
expect(Object.keys(result)).toEqual([]);
});

it('should preserve values after sorting', () => {
const obj = { z: [1, 2], a: { nested: true }, m: 'hello' };
const result = sortKeys(obj);

expect(Object.keys(result)).toEqual(['a', 'm', 'z']);
expect(result.z).toEqual([1, 2]);
expect(result.a).toEqual({ nested: true });
expect(result.m).toBe('hello');
});

it('should handle numeric string keys', () => {
const result = sortKeys({ 3: 'c', 1: 'a', 2: 'b' });
expect(Object.keys(result)).toEqual(['1', '2', '3']);
});

it('should not mutate the original object', () => {
const obj = { b: 2, a: 1 };
const result = sortKeys(obj);

expect(result).not.toBe(obj);
expect(Object.keys(obj)).toEqual(['b', 'a']);
});

it('should handle single-key objects', () => {
const result = sortKeys({ only: 1 });
expect(Object.keys(result)).toEqual(['only']);
expect(result).toEqual({ only: 1 });
});
});
30 changes: 30 additions & 0 deletions src/object/sortKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Creates a new object with the keys sorted.
*
* The keys are sorted alphabetically by default, but a custom compare function can be provided.
*
* @template T - The type of the object.
* @param {T} object - The object to sort keys from.
* @param {(a: string, b: string) => number} [compare] - A custom compare function for sorting keys.
* @returns {T} A new object with the keys sorted.
*
* @example
* sortKeys({ b: 2, a: 1, c: 3 });
* // => { a: 1, b: 2, c: 3 }
*
* @example
* sortKeys({ b: 2, a: 1, c: 3 }, (a, b) => b.localeCompare(a));
* // => { c: 3, b: 2, a: 1 }
*/
export function sortKeys<T extends Record<string, any>>(object: T, compare?: (a: string, b: string) => number): T {
const sortedKeys = Object.keys(object).sort(compare);

const result = {} as Record<string, any>;

for (let i = 0; i < sortedKeys.length; i++) {
const key = sortedKeys[i];
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

result[key] = object[key] will trigger the __proto__ setter on normal objects if the input contains an own enumerable "__proto__" key (e.g. from Object.create(null)), which can mutate result's prototype (prototype pollution). Consider skipping unsafe keys (via the existing isUnsafeProperty helper) and/or defining properties with Object.defineProperty (or creating result with a null prototype) so assigning "__proto__" cannot change the prototype chain.

Suggested change
const key = sortedKeys[i];
const key = sortedKeys[i];
// Skip unsafe keys that could lead to prototype pollution.
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
continue;
}

Copilot uses AI. Check for mistakes.
result[key] = object[key];
}

return result as T;
}
Loading