From 20c0dfb82e4273b10e5a02ba0e74aada42b9bb7a Mon Sep 17 00:00:00 2001 From: Rebecca Stevens Date: Sun, 12 Jun 2022 19:29:47 +1200 Subject: [PATCH] feat: treat module imports as records fix #133 --- package.json | 3 --- src/utils.ts | 48 +++++++++++++++++++++++++++++++++++++++++++++--- yarn.lock | 1 - 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index a6f579c0..bc114821 100644 --- a/package.json +++ b/package.json @@ -78,9 +78,6 @@ "test:js": "c8 ava", "test:types": "dtslint --localTs node_modules/typescript/lib --expectOnly tests/types" }, - "dependencies": { - "is-plain-object": "^5.0.0" - }, "devDependencies": { "@commitlint/cli": "^17.0.2", "@commitlint/config-conventional": "^17.0.2", diff --git a/src/utils.ts b/src/utils.ts index 2aabdd93..8fe1bc5a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,5 +1,3 @@ -import { isPlainObject } from "is-plain-object"; - /** * The different types of objects deepmerge-ts support. */ @@ -27,7 +25,7 @@ export function getObjectType(object: unknown): ObjectType { return ObjectType.ARRAY; } - if (isPlainObject(object)) { + if (isRecord(object)) { return ObjectType.RECORD; } @@ -102,3 +100,47 @@ export function getIterableOfIterables( }, }; } + +const validRecordToStringValues = new Set([ + "[object Object]", + "[object Module]", +]); + +/** + * Does the given object appear to be a record. + */ +function isRecord(value: object): value is Record { + // All records are objects. + if (!validRecordToStringValues.has(Object.prototype.toString.call(value))) { + return false; + } + + const { constructor } = value; + + // If has modified constructor. + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (constructor === undefined) { + return true; + } + + // eslint-disable-next-line prefer-destructuring + const prototype: unknown = constructor.prototype; + + // If has modified prototype. + if ( + prototype === null || + typeof prototype !== "object" || + !validRecordToStringValues.has(Object.prototype.toString.call(prototype)) + ) { + return false; + } + + // If constructor does not have an Object-specific method. + // eslint-disable-next-line sonarjs/prefer-single-boolean-return, no-prototype-builtins + if (!prototype.hasOwnProperty("isPrototypeOf")) { + return false; + } + + // Most likely a record. + return true; +} diff --git a/yarn.lock b/yarn.lock index f22902cc..b465e6f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3488,7 +3488,6 @@ __metadata: eslint-plugin-unicorn: ^42.0.0 husky: ^8.0.1 if-env-defined: ^1.0.0 - is-plain-object: ^5.0.0 lint-staged: ^13.0.1 lodash: ^4.17.21 markdownlint-cli: ^0.31.1