UNPKG

remeda

Version:

A utility library for JavaScript and Typescript.

1 lines 3.35 kB
{"version":3,"file":"keys.cjs","names":["purry"],"sources":["../src/keys.ts"],"sourcesContent":["import type { EnumerableStringKeyOf } from \"./internal/types/EnumerableStringKeyOf\";\nimport type { IterableContainer } from \"./internal/types/IterableContainer\";\nimport type { ToString } from \"./internal/types/ToString\";\nimport { purry } from \"./purry\";\n\ntype Keys<T> = T extends IterableContainer ? ArrayKeys<T> : ObjectKeys<T>;\n\n// The keys output can mirror the input when it is an array/tuple. We do this by\n// \"mapping\" each item \"key\" (which is actually an index) as its own value. This\n// would maintain the shape, even including labels.\ntype ArrayKeys<T extends IterableContainer> = {\n -readonly [Index in keyof T]: Index extends number | string\n ? // Notice that we coalesce the values as strings, this is because in JS,\n // Object.keys always returns strings, even for arrays.\n ToString<IsIndexAfterSpread<T, Index> extends true ? number : Index>\n : // Index is typed as a symbol, this can't happen, but we need to guard\n // against it for typescript.\n never;\n};\n\ntype IsIndexAfterSpread<\n T extends IterableContainer,\n Index extends number | string,\n> =\n IndicesAfterSpread<T> extends never\n ? false\n : Index extends `${IndicesAfterSpread<T>}`\n ? true\n : false;\n\n// Find the index of the tuple where a spread item is located, and return all\n// indices in the tuple which are located after it. The tuple could be prefixed\n// by any number of literal items. If the input is a simple array it would\n// return 0 (as expected), and if the tuple doesn't contain a spread element it\n// would return never.\ntype IndicesAfterSpread<\n T extends ReadonlyArray<unknown> | [],\n // We use this type to count how many items we consumed, it's just a pseudo-\n // element that is used for its length.\n Iterations extends ReadonlyArray<unknown> = [],\n> = T[number] extends never\n ? never\n : T extends readonly [unknown, ...infer Tail]\n ? IndicesAfterSpread<Tail, [unknown, ...Iterations]>\n : T extends readonly [...infer Head, unknown]\n ?\n | IndicesAfterSpread<Head, [unknown, ...Iterations]>\n | Iterations[\"length\"]\n : Iterations[\"length\"];\n\ntype ObjectKeys<T> =\n T extends Record<PropertyKey, never> ? [] : Array<EnumerableStringKeyOf<T>>;\n\n/**\n * Returns a new array containing the keys of the array or object.\n *\n * @param data - Either an array or an object.\n * @signature\n * R.keys(source)\n * @example\n * R.keys(['x', 'y', 'z']); // => ['0', '1', '2']\n * R.keys({ a: 'x', b: 'y', 5: 'z' }); // => ['a', 'b', '5']\n * @dataFirst\n * @category Object\n */\nexport function keys<T extends object>(data: T): Keys<T>;\n\n/**\n * Returns a new array containing the keys of the array or object.\n *\n * @signature\n * R.keys()(source)\n * @example\n * R.Pipe(['x', 'y', 'z'], keys()); // => ['0', '1', '2']\n * R.pipe({ a: 'x', b: 'y', 5: 'z' } as const, R.keys()) // => ['a', 'b', '5']\n * @dataLast\n * @category Object\n */\nexport function keys(): <T extends object>(data: T) => Keys<T>;\n\nexport function keys(...args: ReadonlyArray<unknown>): unknown {\n return purry(Object.keys, args);\n}\n"],"mappings":"wCAgFA,SAAgB,EAAK,GAAG,EAAuC,CAC7D,OAAOA,EAAAA,EAAM,OAAO,KAAM,EAAK"}