-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: avoid isObject
for internal use
#18
Conversation
src/object.ts
Outdated
@@ -275,10 +281,10 @@ export const assign = <X extends Record<string | symbol | number, any>>( | |||
override: X | |||
): X => { | |||
if (!initial || !override) return initial ?? override ?? {} | |||
const merged = { ...initial } | |||
const merged = cloneObject(initial) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Point of discussion
This line changes the behavior of assign
in two subtle ways:
- It copies non-enumerable properties into the new object.
- It copies the prototype into the new object, potentially calling a class constructor.
For these reasons, this is a breaking change, BUT the behavior of assign
is so woefully underspecified that we could probably get away with publishing this in a minor version.
The question is, “what's the intuitive behavior?” One might argue it's whatever aligns with Object.assign
, as this is basically a recursive version of that.
The best course of action is likely to implement a simpler variant of cloneObject
that does { ...initial }
unless an object created with Object.create(null)
is found, in which case, a mixture of Object.create(null)
& Object.assign
is performed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After writing that out, the answer is clear that what I described in the last paragraph is how it should work.
8dc2db5
to
cf58a48
Compare
4beb4ed
to
c938c1b
Compare
79f2cad
to
5e6bfd3
Compare
3e61d98
to
47f126a
Compare
5e6bfd3
to
9dc1b70
Compare
* docs: add warning about `isObject` and `Object.create(null)` * fix: use isPlainObject internally * test: assign/keys with Object.create(null) * fix: preserve null prototype in assign result
Description
Using
isObject
internally is hostile to any use case in need ofObject.create(null)
, so we'll useisPlainObject
instead.Affected functions include:
assign
crush
keys
What does this mean?
When an object created with
Object.create(null)
is nested in the argument toassign
,crush
, orkeys
, it will be treated as if it was created with{}
. In the case ofassign
, any time such an object is assigned to, the resulting clone of the object will have a null prototype as expected.Checklist
/docs
directory) has been updatedResolves
Resolves sodiray/radash#409