1 line
7.6 KiB
Text
1 line
7.6 KiB
Text
|
|
{"version":3,"file":"stringToPath.cjs","names":["result: (string | number)[]","match: RegExpExecArray | null"],"sources":["../src/stringToPath.ts"],"sourcesContent":["import type { IsNumericLiteral, IsStringLiteral } from \"type-fest\";\n\n// This is the most efficient way to check an arbitrary string if it is a simple\n// non-negative integer. We use character ranges instead of the `\\d` character\n// class to avoid matching non-ascii digits (e.g. Arabic-Indic digits), while\n// maintaining that the regular expression supports unicode.\nconst NON_NEGATIVE_INTEGER_RE = /^(?:0|[1-9][0-9]*)$/u;\n\ntype StringToPath<S> =\n // We can only compute the path type for literals that TypeScript can\n // break down further into parts.\n IsStringLiteral<S> extends true ? StringToPathImpl<S> : (string | number)[];\n\ntype StringToPathImpl<S> =\n // We start by checking the 2 quoted variants of the square bracket access\n // syntax. We do this in a single check and not in a subsequent check that\n // would only extract the quoted part so that we can catch cases where the\n // quoted part itself contains square brackets. This allows TypeScript to be\n // \"greedy\" about what it infers into Quoted and DoubleQuoted.\n S extends `${infer Head}['${infer Quoted}']${infer Tail}`\n ? [...StringToPath<Head>, Quoted, ...StringToPath<Tail>]\n : S extends `${infer Head}[\"${infer DoubleQuoted}\"]${infer Tail}`\n ? [...StringToPath<Head>, DoubleQuoted, ...StringToPath<Tail>]\n : // If we have an unquoted property access we also need to run the\n // contents recursively too (unlike the quoted variants above).\n S extends `${infer Head}[${infer Unquoted}]${infer Tail}`\n ? [\n ...StringToPath<Head>,\n ...StringToPath<Unquoted>,\n ...StringToPath<Tail>,\n ]\n : // Finally, we process any dots one after the other from left to\n // right. TypeScript will be non-greedy here, putting *everything*\n // after the first dot into the Tail.\n S extends `${infer Head}.${infer Tail}`\n ? [...StringToPath<Head>, ...StringToPath<Tail>]\n : // Finally we need to handle the few cases of simple literals.\n \"\" extends S\n ? // There are some edge-cases where Lodash will try to access an\n // empty property, but those seem nonsensical in practice so we\n // prefer just skipping these cases.\n []\n : // We differ from Lodash in the way we handle numbers. Lodash\n // returns everything in the path as a string, and relies on JS to\n // coerce array accessors to numbers (or the other way around in\n // practice, e.g., `myArray[123] === myArray['123']`), but from a\n // typing perspective the two are not the same and we need the\n // path to be accurate about it.\n S extends `${infer N extends number}`\n ? [\n // TypeScript considers \" 123 \" to still extend `${number}`,\n // but would type is as `string` instead of a literal. We\n // can use that fact to make sure we only consider simple\n // number literals as numbers, and take the rest as strings.\n IsNumericLiteral<N> extends true ? N : S,\n ]\n : // This simplest form of a path is just a single string literal.\n [S];\n\n/**\n * A utility to allow JSONPath-like strings to be used in other utilities which\n * take an array of path segments as input (e.g. `prop`, `setPath`, etc...).\n * The main purpose of this utility is to act as a bridge between the runtime\n * implementation that converts the path to an array, and the type-system that\n * parses the path string **type** into an array **type**. This type allows us\n * to return fine-grained types and to enforce correctness at the type-level.\n *\n * We **discourage** using this utility for new code. This utility is for legacy\n * code that
|