npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

typedots

v0.0.4

Published

A simple way to get and set object properties using paths (aka dot notation) with TypeScript support

Downloads

179

Readme

Features

Runtime

  • [X] Get object property value from path: get(obj, 'prop.subprop')
  • [X] Set object property value from path: set(obj, 'prop.subprop', 'value')
  • [X] Check if object has property from path: has(obj, 'prop.subprop')
  • [X] Supports property names containing dots: {'my.property': true}

While developing

  • [X] Path argument is autocompleted based on the object you pass.
  • [X] Strict mode to force path argument to only match possible paths.
  • [X] Ability to filter out suggested paths based on a given type.

Install

Open in Codeflow

# Using npm
npm i typedots
# Using Yarn
yarn add typedots
# Using pnpm
pnpm add typedots

Usage

There are two ways of consuming typedots depending on your needs and preferences:

Directly use base methods

import { get, set, has } from 'typedots';

Advanced use through class

The class implements the exact same base methods.

import Typedots from 'typedots';

const td = new Typedots(); // td.get, td.set, td.has

It is mainly used to get finer control over the way typedots' type system behaves as further explored in Advanced usage.

Methods

get

set

has

Note When one of the properties in the path contains a dot, such property should be wrapped with parentheses so that it does not conflict with typedots inner workings. e.g. "sites.(my.host.com).ip"

Advanced usage

By default, using the base methods does not enforce the path arguments to actually strictly match one of the values provided by autocompletion. Those are just bare suggestions and you may pass any other string without TypeScript yelling at you.

Additionally, when drawing up the list of suggestions, all paths resolving to non-object properties are automatically picked.

Both behaviours may be tweaked by making use of the Typedots class instead of the base methods. It provides a generic type which is constrained to the following interface:

export interface TypedotsParams = {
  expectedType?: any;
  strictMode?: boolean;
  preventDistribution?: boolean;
}

Filter out suggestions by type

You may want to add some constraints to the list of suggested paths. To achieve this, you can use typedots' class and set the expectedType parameter in its generic type. Once set, only properties matching the type you passed in expectedType will be suggested in the path arguments. Here's a quick example which should only suggest paths resolving to functions:

const obj = {
  myProperty: 'value of my property',
  myMethod: (message) => `received ${message}`,
  helpers: { maxLength: 255, count(item) { return item.length; } },
};

const typedots = new Typedots<{ expectedType: (...args: any) => any }>();
const method = typedots.get(obj, ''); // <-- should only suggest "myMethod" and "helpers.count"

Please note that typedots relies on TypeScript's own type inference mechanism. This means its behaviour may be influenced by TypeScript's configuration.

False, undefined and null values

For example, strictNullChecks changes the way types are infered:

/** > When `strictNullChecks: false`: */
// infered as { prop, string un: any }
const obj = { prop: 'some string', un: undefined };
new Typedots<{ expectedType: string }>(); // suggests "prop" | "un"

/** > When `strictNullChecks: true`: */
// infered as { prop: string, un: undefined }
const obj = { prop: 'some string', un: undefined };
new Typedots<{ expectedType: string }>(); // suggests "prop"

Boolean distributivity

Because conditional types in generic parameters are distributive, when specifically expecting true or false types, paths resolving to boolean are also suggested since they match (boolean = true | false).

// infered as { one: boolean, two: boolean, tree: boolean }
const obj = { one: false, two: true, three: true as boolean };
new Typedots<{ expectedType: true }>(); // suggests "one" | "two" | "three"

// infered as { one: false, two: true, tree: boolean }
const obj = { one: false, two: true, three: true as boolean } as const;
new Typedots<{ expectedType: true }>(); // suggests "two" | "three"

You may want to go even stricter by preventing boolean to be distributed when expecting false or true. To achieve this, you can use typedots' class and set the preventDistribution parameter in its generic type:

// infered as { one: boolean, two: boolean, tree: boolean }
const obj = { one: false, two: true, three: true as boolean };
new Typedots<{ expectedType: true, preventDistribution: true }>(); // no suggestion

// infered as { one: false, two: true, tree: boolean }
const obj = { one: false, two: true, three: true as boolean } as const;
new Typedots<{ expectedType: true, preventDistribution: true }>(); // suggests "two"

Strict mode

You can get TypeScript to ensure you're actually using one of the suggested paths, and not any other string. To achieve this, you can use typedots' class and set the strictMode parameter in its generic type. Once set, TypeScript should raise errors any time you set the path arguments to a string value which was not suggested.

const obj = {
  myProperty: 'value of my property',
  myMethod: (message) => `received ${message}`,
  helpers: { maxLength: 255, count(item) { return item.length; } },
};

const typedots = new Typedots<{ strictMode: true }>();
typedots.get(obj, 'myProperty'); // <-- works!
typedots.get(obj, 'helpers.maxLength'); // <-- works!
typedots.get(obj, 'oops'); // <-- should raise a TypeScript error
typedots.get(obj, 'helpers.oops'); // <-- should raise a TypeScript error

Note that both expectedType and strictMode can be combined to work together:

const typedots = new Typedots<{
  strictMode: true,
  expectedType: (...args: any) => any },
}>();
typedots.get(obj, 'myMethod'); // <-- works!
typedots.get(obj, 'helpers.count'); // <-- works!
typedots.get(obj, 'myProperty'); // <-- should raise a TypeScript error
typedots.get(obj, 'helpers.maxLength'); // <-- should raise a TypeScript error

Exported type

The type which powers the suggestion system is exported as ExtractObjectPaths, you may be interested in using it even if you're not actually using the runtime methods. It takes three generic parameters:

  1. BaseObject, which extends any non-null object.
  2. ExpectedType, see Filter out suggestions by type
  3. PreventDistribution, see Boolean distributivity

Examples

import { get, set, has } from 'typedots';

const variableName = 'content';
const baseObject = {
  prop1: true,
  prop2: false,
  prop3: {
    subprop1: 'string',
    subprop2: ['first', 2_000, { third: undefined }],
    subprop3: { one: true, two: true, three: false },
    subprop4: undefined,
  },
  [variableName]: {},
  'prop.5': { nested: 'string', 'another.sub.prop': {} },
};

get(baseObject, 'prop1'); // true
get(baseObject, 'prop3.subprop1'); // "string"
get(baseObject, 'prop3.subprop3.three'); // false
get(baseObject, '(prop.5).nested'); // 'string'
get(baseObject, 'content'); // {}
get(baseObject, variableName); // {}

set(baseObject, 'prop1', value); // true
set(baseObject, 'prop100', value, false); // false
set(baseObject, 'prop100', value); // true
set(baseObject, 'prop2.child', value, false); // false
set(baseObject, 'prop2.child', value); // true

has(baseObject, 'prop1'); // true
has(baseObject, 'prop3.NOOP'); // false
has(baseObject, 'NOPE'); // false
has(baseObject, 'prop3.subprop4'); // true
has(baseObject, '(prop.5).(another.sub.prop)'); // true