Security News
New Python Packaging Proposal Aims to Solve Phantom Dependency Problem with SBOMs
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
existential-proxy
Advanced tools
Type safe existential property access using ES6 proxies
This library gives you the ability to get
, set
, or update
(with an update function) values nested within an object who's keys may be nullable (undefined
or null
), without mutating the original input, or having to worry about checking for values' existence.
Optional chaining in JavaScript / TypeScript is not yet finalized, and so we need a way to safely access nested values that may or may not exist.
This library was created for use with TypeScript to give sensible types when accessing nullable nested values without having to specify the types yourself.
Although designed with TypeScript in mind, existential-proxy works perfectly well with JavaScript.
Unlike destructuring with default values existential-proxy allows access through values that may be undefined
or null
without specifying default values for each level, and allows specifying defaults even when the value may be null
.
Additionally, unlike (some) alternatives that allow access to nested properties this library also allows setting or updating values inside a nested object in an immutable way (returning a copy of the input with updated values as necessary).
I intend to add a function to create a selector, much like reselect, to allow transforming values only when changed, but using proxies removing the need to null check nested values.
Install existential-proxy with NPM (-S
will automatically add this to your package.json
):
npm i existential-proxy -S
I'd recommend importing * as
so that you can easily tell where the functions are coming from, and avoid naming conflicts (as many libraries will use similarly named functions).
import * as ep from 'existential-proxy';
Almost of the examples below will use the following types / object.
// Here's an example object type
interface ABC {
a: {
b?: {
c: string;
};
} | null;
}
// Here's our example object
const abc: ABC = {
a: {} // Note that the b key does not exist
};
The get
function takes 3 arguments:
// Access without defaults
ep.get(abc, (proxy) => proxy); // ABC
ep.get(abc, (proxy) => proxy.a); // { b?: { c: string; } } | null
ep.get(abc, (proxy) => proxy.a.b); // { c: string; } | undefined
ep.get(abc, (proxy) => proxy.a.b.c); // string | undefined
// Access with defaults
ep.get(abc, (proxy) => proxy, 'whatever'); // ABC
ep.get(abc, (proxy) => proxy.a, { b: { c: 'hello' } }); // { b?: { c: string; } } | { b: { c: string; } }
ep.get(abc, (proxy) => proxy.a.b, { c: 'hello' }); // { c: string; }
ep.get(abc, (proxy) => proxy.a.b.c, 'hello'); // string
The set
function takes 3 arguments:
// Will return the provided value (essentially replacing the input object)
ep.set(abc, (proxy) => proxy, { a: { b: { c: 'hello' } } }); // { a: { b: { c: 'hello' } } }: ABC
// Will return a copy of the `abc` object with a new `a` value
ep.set(abc, (proxy) => proxy.a, { b: { c: 'hello' } }); // { a: { b: { c: 'hello' } } }: ABC
// Will return a copy of the `abc` object with a new `b` value
ep.set(abc, (proxy) => proxy.a.b, { c: 'hello' }); // { a: { b: { c: 'hello' } } }: ABC
The update
function takes 3 arguments:
// Will return the returned value (essentially replacing the input object)
ep.update(abc, (proxy) => proxy, () => ({ a: { b: { c: 'hello' } } })); // { a: { b: { c: 'hello' } } }: ABC
// Will return a copy of the `abc` object with a new `a` value if it is not defined
ep.update(abc, (proxy) => proxy.a, (a) => {
if (!a) {
return { b: { c: 'hello' } };
}
return a;
}); // { a: { b: { c: 'hello' } } }: ABC
// Will return a copy of the `abc` object with a new `b` value if it is not defined
ep.update(abc, (proxy) => proxy.a.b, (b) => {
if (!b) {
return { c: 'hello' };
}
return b;
}); // { a: { b: { c: 'hello' } } }: ABC
When using set
and update
you should note that:
undefined
or null
. This is because there is no way to detect if trying to access values from an array or object if the target is not already an array or object (all keys; .a
, [0]
, are only available as strings when using a proxy).This library's set
and update
functions may not give you the output you'd expect if you are using integers as keys in objects.
interface NumKey {
a?: {
0: string;
};
}
const numKey: NumKey = {};
// Will create an array when trying to access the `0` key
ep.set(numKey, (proxy) => proxy.a[0], 'hello'); // { a: ['hello'] }: NumKey
// Will still create an array when trying to access the `0` key
ep.set(numKey, (proxy) => proxy.a['0'], 'hello'); // { a: ['hello'] }: NumKey
FAQs
Type safe existential property access using ES6 proxies
We found that existential-proxy demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
Security News
Socket CEO Feross Aboukhadijeh discusses open source security challenges, including zero-day attacks and supply chain risks, on the Cyber Security Council podcast.
Security News
Research
Socket researchers uncover how threat actors weaponize Out-of-Band Application Security Testing (OAST) techniques across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.