remeda
Version:
A utility library for JavaScript and Typescript.
1 lines • 4.31 kB
Source Map (JSON)
{"version":3,"file":"hasSubObject.cjs","names":["purry","isDeepEqual"],"sources":["../src/hasSubObject.ts"],"sourcesContent":["import type { Simplify, Tagged } from \"type-fest\";\nimport { isDeepEqual } from \"./isDeepEqual\";\nimport { purry } from \"./purry\";\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars -- We want to confine the typing to a specific symbol\ndeclare const HAS_SUB_OBJECT_BRAND: unique symbol;\n\ntype HasSubObjectGuard<T, S> = Simplify<\n Tagged<S & T, typeof HAS_SUB_OBJECT_BRAND>\n>;\n\ntype HasSubObjectObjectValue<A, B> = Partial<{\n [Key in keyof A & keyof B]: A[Key] & B[Key] extends never\n ? B[Key]\n : A[Key] | B[Key] extends object\n ? HasSubObjectObjectValue<A[Key], B[Key]>\n : A[Key] & B[Key] extends object\n ? B[Key]\n : A[Key];\n}> & {\n [Key in\n | Exclude<keyof A, keyof B>\n | Exclude<keyof B, keyof A>]: Key extends keyof B ? B[Key] : never;\n};\n\ntype HasSubObjectData<\n Data,\n SubObject,\n RData = Required<Data>,\n RSubObject = Required<SubObject>,\n> = Partial<{\n [Key in keyof RData & keyof RSubObject]: RData[Key] &\n RSubObject[Key] extends never\n ? RSubObject[Key]\n : RData[Key] | RSubObject[Key] extends object\n ? HasSubObjectObjectValue<RData[Key], RSubObject[Key]>\n : RData[Key] & RSubObject[Key] extends object\n ? RSubObject[Key]\n : RData[Key];\n}> & {\n [Key in Exclude<keyof SubObject, keyof Data>]: SubObject[Key];\n};\n\ntype HasSubObjectSubObject<\n SubObject,\n Data,\n RSubObject = Required<SubObject>,\n RData = Required<Data>,\n> = Partial<{\n [Key in keyof RData & keyof RSubObject]: RData[Key] &\n RSubObject[Key] extends never\n ? RData[Key]\n : RData[Key] | RSubObject[Key] extends object\n ? HasSubObjectObjectValue<RSubObject[Key], RData[Key]>\n : RData[Key] & RSubObject[Key] extends object\n ? RData[Key]\n : RSubObject[Key];\n}> &\n Record<Exclude<keyof SubObject, keyof Data>, never>;\n\n/**\n * Checks if `subObject` is a sub-object of `object`, which means for every\n * property and value in `subObject`, there's the same property in `object`\n * with an equal value. Equality is checked with `isDeepEqual`.\n *\n * @param data - The object to test.\n * @param subObject - The sub-object to test against.\n * @signature\n * R.hasSubObject(data, subObject)\n * @example\n * R.hasSubObject({ a: 1, b: 2, c: 3 }, { a: 1, c: 3 }) //=> true\n * R.hasSubObject({ a: 1, b: 2, c: 3 }, { b: 4 }) //=> false\n * R.hasSubObject({ a: 1, b: 2, c: 3 }, {}) //=> true\n * @dataFirst\n * @category Guard\n */\nexport function hasSubObject<\n T extends object,\n S extends HasSubObjectSubObject<S, T>,\n>(data: T, subObject: S): data is HasSubObjectGuard<T, S>;\n\n/**\n * Checks if `subObject` is a sub-object of `object`, which means for every\n * property and value in `subObject`, there's the same property in `object`\n * with an equal value. Equality is checked with `isDeepEqual`.\n *\n * @param subObject - The sub-object to test against.\n * @signature\n * R.hasSubObject(subObject)(data)\n * @example\n * R.hasSubObject({ a: 1, c: 3 })({ a: 1, b: 2, c: 3 }) //=> true\n * R.hasSubObject({ b: 4 })({ a: 1, b: 2, c: 3 }) //=> false\n * R.hasSubObject({})({ a: 1, b: 2, c: 3 }) //=> true\n * @dataLast\n * @category Guard\n */\nexport function hasSubObject<S extends object>(\n subObject: S,\n): <T extends HasSubObjectData<T, S>>(\n data: T,\n) => data is HasSubObjectGuard<T, S>;\n\nexport function hasSubObject(...args: ReadonlyArray<unknown>): unknown {\n return purry(hasSubObjectImplementation, args);\n}\n\nfunction hasSubObjectImplementation<\n T extends Record<PropertyKey, unknown>,\n S extends Record<PropertyKey, unknown>,\n>(data: T, subObject: S): data is HasSubObjectGuard<T, S> {\n for (const [key, value] of Object.entries(subObject)) {\n if (!Object.hasOwn(data, key)) {\n return false;\n }\n\n if (!isDeepEqual(value, data[key])) {\n return false;\n }\n }\n\n return true;\n}\n"],"mappings":"uEAsGA,SAAgB,EAAa,GAAG,EAAuC,CACrE,OAAOA,EAAAA,EAAM,EAA4B,EAAK,CAGhD,SAAS,EAGP,EAAS,EAA+C,CACxD,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAU,CAKlD,GAJI,CAAC,OAAO,OAAO,EAAM,EAAI,EAIzB,CAACC,EAAAA,YAAY,EAAO,EAAK,GAAK,CAChC,MAAO,GAIX,MAAO"}