From 15bbebcec1967d3bb89fa18745321d169ebc0798 Mon Sep 17 00:00:00 2001 From: Seojooyeon-creat <79130628+Seojooyeon-creat@users.noreply.github.com> Date: Mon, 2 Mar 2026 15:43:43 +0900 Subject: [PATCH 1/2] fix(pick): return Partial> for non-tuple key arrays --- src/object/pick.spec.ts | 17 ++++++++++++++++- src/object/pick.ts | 17 ++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/object/pick.spec.ts b/src/object/pick.spec.ts index 8efb5d5c0..fbab6a18b 100644 --- a/src/object/pick.spec.ts +++ b/src/object/pick.spec.ts @@ -1,4 +1,4 @@ -import { describe, expect, it } from 'vitest'; +import { describe, expect, expectTypeOf, it } from 'vitest'; import { pick } from './pick'; describe('pick', () => { @@ -32,4 +32,19 @@ describe('pick', () => { expect(Reflect.ownKeys(result)).toEqual([]); }); + + it('should return Pick when given a literal tuple (all keys guaranteed)', () => { + const obj = { a: 1, b: 2, c: 3 }; + const result = pick(obj, ['a', 'b']); + + expectTypeOf(result).toEqualTypeOf>(); + }); + + it('should return Partial> when given a non-tuple array (not all keys guaranteed)', () => { + const obj = { a: 1, b: 2, c: 3 }; + const keys: ('a' | 'b')[] = Math.random() > 0.5 ? ['a'] : ['b']; + const result = pick(obj, keys); + + expectTypeOf(result).toEqualTypeOf>>(); + }); }); diff --git a/src/object/pick.ts b/src/object/pick.ts index 8e24bb20f..9dd580c6c 100644 --- a/src/object/pick.ts +++ b/src/object/pick.ts @@ -4,19 +4,26 @@ * This function takes an object and an array of keys, and returns a new object that * includes only the properties corresponding to the specified keys. * + * The return type depends on whether a tuple or a variable-length array is passed: + * - Tuple (e.g. `['a', 'b']`): returns `Pick` — all keys are guaranteed present. + * - Array (e.g. `keys: ('a' | 'b')[]`): returns `Partial>` — only some keys may be present. + * * @template T - The type of object. - * @template K - The type of keys in object. + * @template Keys - The type of the keys array (tuple or array). * @param {T} obj - The object to pick keys from. - * @param {K[]} keys - An array of keys to be picked from the object. - * @returns {Pick} A new object with the specified keys picked. + * @param {Keys} keys - An array of keys to be picked from the object. + * @returns A new object with the specified keys picked. * * @example * const obj = { a: 1, b: 2, c: 3 }; * const result = pick(obj, ['a', 'c']); * // result will be { a: 1, c: 3 } */ -export function pick, K extends keyof T>(obj: T, keys: readonly K[]): Pick { - const result = {} as Pick; +export function pick, Keys extends ReadonlyArray>( + obj: T, + keys: readonly [...Keys] +): number extends Keys['length'] ? Partial> : Pick { + const result = {} as any; for (let i = 0; i < keys.length; i++) { const key = keys[i]; From 59896357a08d6ea794af2d53f080d1a7a15e97dc Mon Sep 17 00:00:00 2001 From: Seojooyeon-creat <79130628+Seojooyeon-creat@users.noreply.github.com> Date: Wed, 4 Mar 2026 15:52:30 +0900 Subject: [PATCH 2/2] docs(pick): update return type description for tuple vs array distinction Co-Authored-By: Claude Sonnet 4.6 --- docs/ja/reference/object/pick.md | 7 +++++-- docs/ko/reference/object/pick.md | 7 +++++-- docs/reference/object/pick.md | 7 +++++-- docs/zh_hans/reference/object/pick.md | 7 +++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/docs/ja/reference/object/pick.md b/docs/ja/reference/object/pick.md index 4f0c14d09..9f44deec8 100644 --- a/docs/ja/reference/object/pick.md +++ b/docs/ja/reference/object/pick.md @@ -37,8 +37,11 @@ const picked = pick(nested, ['user', 'settings']); #### パラメータ - `obj` (`T extends Record`): プロパティを選択するオブジェクトです。 -- `keys` (`readonly K[]`): オブジェクトから選択するキーの配列です。 +- `keys` (`readonly [...Keys]`): オブジェクトから選択するキーの配列またはタプルです。 #### 戻り値 -(`Pick`): 指定されたキーに対応するプロパティのみを含む新しいオブジェクトを返します。 +`keys`がタプルか可変長配列かによって、戻り値の型が変わります。 + +- `keys`が**タプル**の場合(例: `['a', 'b']`): `Pick` を返します — 指定したキーがすべて存在することが保証されます。 +- `keys`が**可変長配列**の場合(例: `keys: ('a' | 'b')[]`): `Partial>` を返します — 配列に実際に含まれているキーのみが結果オブジェクトに存在します。 diff --git a/docs/ko/reference/object/pick.md b/docs/ko/reference/object/pick.md index c04bd0aee..1b51d3423 100644 --- a/docs/ko/reference/object/pick.md +++ b/docs/ko/reference/object/pick.md @@ -37,8 +37,11 @@ const picked = pick(nested, ['user', 'settings']); #### 파라미터 - `obj` (`T extends Record`): 속성들을 선택할 객체예요. -- `keys` (`readonly K[]`): 객체에서 선택할 키들의 배열이에요. +- `keys` (`readonly [...Keys]`): 객체에서 선택할 키들의 배열 또는 튜플이에요. #### 반환 값 -(`Pick`): 지정된 키들에 해당하는 속성들만 포함한 새로운 객체를 반환해요. +`keys`가 튜플인지 가변 길이 배열인지에 따라 반환 타입이 달라져요. + +- `keys`가 **튜플**인 경우 (예: `['a', 'b']`): `Pick`를 반환해요 — 지정된 키들이 모두 존재하는 것이 보장돼요. +- `keys`가 **가변 길이 배열**인 경우 (예: `keys: ('a' | 'b')[]`): `Partial>`를 반환해요 — 배열에 실제로 포함된 키들만 결과 객체에 존재해요. diff --git a/docs/reference/object/pick.md b/docs/reference/object/pick.md index ceb9ae012..b427c1d5f 100644 --- a/docs/reference/object/pick.md +++ b/docs/reference/object/pick.md @@ -37,8 +37,11 @@ const picked = pick(nested, ['user', 'settings']); #### Parameters - `obj` (`T extends Record`): The object to select properties from. -- `keys` (`readonly K[]`): An array of keys to select from the object. +- `keys` (`readonly [...Keys]`): An array or tuple of keys to select from the object. #### Returns -(`Pick`): A new object containing only the properties corresponding to the specified keys. +The return type depends on whether `keys` is a tuple or a variable-length array: + +- If `keys` is a **tuple** (e.g. `['a', 'b']`): returns `Pick` — all specified keys are guaranteed to be present. +- If `keys` is a **variable-length array** (e.g. `keys: ('a' | 'b')[]`): returns `Partial>` — only the keys actually in the array will be present. diff --git a/docs/zh_hans/reference/object/pick.md b/docs/zh_hans/reference/object/pick.md index 8c627619c..b85892c95 100644 --- a/docs/zh_hans/reference/object/pick.md +++ b/docs/zh_hans/reference/object/pick.md @@ -37,8 +37,11 @@ const picked = pick(nested, ['user', 'settings']); #### 参数 - `obj` (`T extends Record`): 要选择属性的对象。 -- `keys` (`readonly K[]`): 要从对象中选择的键的数组。 +- `keys` (`readonly [...Keys]`): 要从对象中选择的键的数组或元组。 #### 返回值 -(`Pick`): 返回一个仅包含指定键对应属性的新对象。 +返回类型取决于 `keys` 是元组还是可变长度数组。 + +- 如果 `keys` 是**元组**(例如 `['a', 'b']`):返回 `Pick` — 保证所有指定的键都存在。 +- 如果 `keys` 是**可变长度数组**(例如 `keys: ('a' | 'b')[]`):返回 `Partial>` — 只有数组中实际包含的键才会出现在结果对象中。