UNPKG

typedash

Version:

modern, type-safe collection of utility functions

1 lines 7.08 kB
{"version":3,"sources":["../../src/functions/createTypeGuard/createTypeGuard.ts","../../src/functions/_internal/isMaliciousObjectPath.ts","../../src/functions/compact/compact.ts","../../src/functions/assert/assert.ts","../../src/functions/set/set.ts"],"names":[],"mappings":";AAeO,SAAS,gBAId,QAAyE;AACzE,QAAM,YAAY,IAAI,IAAa,MAAM;AACzC,SAAO,SAAS,UAAU,GAAuC;AAC/D,WAAO,UAAU,IAAI,CAAC;AAAA,EACxB;AACF;;;ACXO,IAAM,4BAA4B;AAAA,EACvC,OAAO,oBAAoB,OAAO,eAAe,CAAC,CAAC,CAAC;AACtD;;;ACHO,SAAS,QAAW,OAA8C;AACvE,SAAQ,OAAO,OAAO,OAAO,KAAyB,CAAC;AACzD;;;ACSO,SAAS,OACd,WACA,SACmB;AACnB,MAAI,UAAU,WAAW,GAAG;AAC1B;AAAA,EACF;AAEA,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,eAAe,OAAO;AAAA,EAClC;AACF;AAMO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC,YAAY,SAAkB;AAC5B;AAAA,MACE,QAAQ;AAAA,QACN;AAAA,QACA,UAAU,MAAM,OAAO,MAAM;AAAA,MAC/B,CAAC,EAAE,KAAK,EAAE;AAAA,IACZ;AAAA,EACF;AACF;;;ACtBO,SAAS,IAId,QACA,MACA,OAC4D;AAC5D,QAAM,WAAW,KAAK,MAAM,iBAAiB;AAC7C,SAAO,aAAa,MAAM,cAAc;AACxC;AAAA,IACE,SAAS,MAAM,CAAC,YAAY,0BAA0B,OAAO,MAAM,KAAK;AAAA,IACxE;AAAA,EACF;AAGA,MAAI,gBAAqB;AACzB,WAAS,QAAQ,GAAG,QAAQ,SAAS,SAAS,GAAG,SAAS;AAExD,UAAM,UAAU,SAAS,KAAK;AAC9B,QAAI,WAAW,kBAAkB,OAAO;AAEtC,oBAAc,OAAO,IAAI,CAAC;AAAA,IAC5B;AAEA,oBAAgB,cAAc,OAAO;AAAA,EACvC;AAGA,gBAAc,SAAS,GAAG,EAAE,CAAE,IAAI;AACpC;AAEA,IAAM,oBAAoB","sourcesContent":["/**\n * Creates a type guard that checks if the given type is assignable to the given type.\n * @param values The values to check against.\n * @template {TInput} The type to check against, `unknown` by default. Pass in if you want to have a narrowed type for the type predicate (e.g. `string`).\n * @returns A type guard that checks if the given type is assignable to the given type.\n * @example\n * ```ts\n * const isValidValue = createTypeGuard(['foo', 'bar']);\n *\n * const value: unknown = '...';\n * if (isValidValue(value)) {\n * // ✅ value is of type `'foo' | 'bar'`\n * }\n * ```\n */\nexport function createTypeGuard<\n const TKnownValue,\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents -- without this we can't have a default type of `unknown`\n TInput extends TKnownValue | unknown = unknown,\n>(values: Iterable<TKnownValue>): (v: TInput) => v is TInput & TKnownValue {\n const setValues = new Set<unknown>(values);\n return function predicate(v: unknown): v is TInput & TKnownValue {\n return setValues.has(v);\n };\n}\n","import { createTypeGuard } from '../createTypeGuard';\n\n/**\n * Determines whether the given property name is malicious or not (e.g. `__proto__` or `constructor`).\n * @param propertyName The property name to check for maliciousness.\n * @returns true if the property name is malicious, false otherwise.\n * @example\n * ```ts\n * isMaliciousObjectProperty('constructor'); // returns true\n * isMaliciousObjectProperty('nonMaliciousPath'); // returns false\n * isMaliciousObjectProperty('__proto__'); // returns true\n * ```\n */\nexport const isMaliciousObjectProperty = createTypeGuard<string, string>(\n Object.getOwnPropertyNames(Object.getPrototypeOf({}))\n);\n","import { Falsey, Maybe } from '../../types';\n\n/**\n * Creates an array with all falsey values removed.\n * The values `false`, `null`, `0`, `\"\"`, `undefined`, and `NaN` are falsey.\n * @param array The array to compact.\n * @returns The new array of filtered values.\n * @example\n * ```ts\n * compact([0, 1, false, 2, '', 3, null, 4, undefined]) // [1, 2, 3, 4]\n * ```\n */\nexport function compact<T>(array: Maybe<ReadonlyArray<T | Falsey>>): T[] {\n return (array?.filter(Boolean) as T[] | undefined) ?? [];\n}\n","import { compact } from '../compact';\n\n/**\n * Asserts that a condition is true, throwing an Error if it is not.\n * @param condition A condition that should be true\n * @param message A message to use in the Error that will be thrown if the condition is falsy\n * @throws An `AssertionError` if the condition is falsy\n * @example\n * ```ts\n * function doWork(value: number | undefined) {\n * assert(value !== undefined, 'value should be defined');\n * // value is now narrowed to number\n *\n * return value + 1;\n * }\n * ```\n * @example\n * ```ts\n * assert(1 === 1); // OK\n * assert(1 === 2); // throws AssertionError\n * assert(1 === 2, '1 should equal 2'); // throws AssertionError: 1 should equal 2\n * ```\n */\nexport function assert(\n condition?: unknown,\n message?: string\n): asserts condition {\n if (arguments.length === 0) {\n return;\n }\n\n if (!condition) {\n throw new AssertionError(message);\n }\n}\n\n/**\n * An error that is thrown when an assertion is not satisfied.\n * Thrown by {@link assert}.\n */\nexport class AssertionError extends Error {\n constructor(message?: string) {\n super(\n compact([\n `Assertion not satisfied`,\n message ? `: \"${message}\"` : '',\n ]).join('')\n );\n }\n}\n","import type { Get } from 'type-fest';\n\nimport { ObjectPath } from '../../types';\nimport { RequireKeysDeep } from '../../types/_internal';\nimport { isMaliciousObjectProperty } from '../_internal/isMaliciousObjectPath';\nimport { assert } from '../assert';\n\n/**\n * Sets a value at the specified (possibly nested) path in an object.\n * @template TObject The type of the object.\n * @template Path The type of the path.\n * @param object The object to set the value in.\n * @param path The path to set the value at.\n * @param value The value to set.\n * @example\n * ```ts\n * const object: {\n * foo?: {\n * bar?: {\n * anArray: string[];\n * };\n * }\n * };\n *\n * set(object, 'foo.bar.anArray[0]', 'value');\n * object.foo.bar.anArray[0]; // 'value'\n */\nexport function set<\n TObject extends Record<string, unknown>,\n Path extends ObjectPath<TObject>,\n>(\n object: TObject,\n path: Path,\n value: Get<TObject, Path>\n): asserts object is TObject & RequireKeysDeep<TObject, Path> {\n const segments = path.match(pathSegmentsRegex);\n assert(segments !== null, 'Invalid path');\n assert(\n segments.every((segment) => isMaliciousObjectProperty(segment) === false),\n 'Potentially malicious path'\n );\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- easier to work with, and we're trusting the compiler\n let currentObject: any = object;\n for (let index = 0; index < segments.length - 1; index++) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- trust the compiler (and unit tests 😄).\n const segment = segments[index]!;\n if (segment in currentObject === false) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we're initializing the `segment` property\n currentObject[segment] = {};\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n currentObject = currentObject[segment];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access -- this is checked at the type-level\n currentObject[segments.at(-1)!] = value;\n}\n\nconst pathSegmentsRegex = /[\\w-]+/g;\n"]}