CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-polkadot--util

A collection of useful utilities for @polkadot ecosystem with type checking, data conversion, and performance optimization functions

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

objects.mddocs/

Object Utilities

Object manipulation helpers for property access, copying, transformation, and introspection operations in JavaScript/TypeScript applications.

Capabilities

Object Property Access

Functions for accessing and manipulating object properties with type safety.

/**
 * Gets all keys from an object with proper typing
 * @param value - Object to get keys from
 */
function objectKeys<T>(value: T): (keyof T)[];

/**
 * Gets all values from an object
 * @param value - Object to get values from  
 */
function objectValues<T>(value: T): T[keyof T][];

/**
 * Gets key-value pairs from an object as tuples
 * @param value - Object to get entries from
 */
function objectEntries<T>(value: T): [keyof T, T[keyof T]][];

Object Manipulation

Core functions for copying, spreading, and clearing objects.

/**
 * Creates a shallow copy of an object
 * @param source - Object to copy
 */
function objectCopy<T>(source: T): T;

/**
 * Spreads properties from source objects to destination
 * @param dest - Destination object
 * @param sources - Source objects to spread from
 */
function objectSpread<T, S>(dest: T, ...sources: S[]): T & S;

/**
 * Clears all properties from an object
 * @param value - Object to clear
 */
function objectClear(value: Record<string, unknown>): Record<string, unknown>;

Property Introspection

Advanced functions for examining object property descriptors.

/**
 * Gets property descriptors for all properties
 * @param value - Object to examine
 */
function objectProperties(value: Record<string, unknown>): Record<string, PropertyDescriptor>;

/**
 * Gets property descriptor for a single property
 * @param value - Object to examine
 * @param property - Property name to get descriptor for
 */
function objectProperty(value: Record<string, unknown>, property: string): PropertyDescriptor | undefined;

Usage Examples

Object Property Access:

import { objectKeys, objectValues, objectEntries } from "@polkadot/util";

const user = {
  id: 123,
  name: "Alice",
  email: "alice@example.com",
  active: true
};

// Get typed keys
const keys = objectKeys(user); // ("id" | "name" | "email" | "active")[]
console.log(keys); // ["id", "name", "email", "active"]

// Get all values
const values = objectValues(user); // (string | number | boolean)[]
console.log(values); // [123, "Alice", "alice@example.com", true]

// Get key-value pairs
const entries = objectEntries(user);
console.log(entries); 
// [["id", 123], ["name", "Alice"], ["email", "alice@example.com"], ["active", true]]

// Use entries for transformation
const uppercaseKeys = Object.fromEntries(
  entries.map(([key, value]) => [key.toUpperCase(), value])
);
console.log(uppercaseKeys); // { ID: 123, NAME: "Alice", ... }

Object Copying and Spreading:

import { objectCopy, objectSpread } from "@polkadot/util";

const original = { name: "John", age: 30 };

// Create shallow copy
const copy = objectCopy(original);
copy.age = 31; // Doesn't affect original
console.log(original.age); // 30
console.log(copy.age); // 31

// Spread properties into new object
const defaults = { theme: "dark", notifications: true };
const userPrefs = { theme: "light" };
const final = objectSpread({}, defaults, userPrefs);
console.log(final); // { theme: "light", notifications: true }

// Spread into existing object
const target = { id: 1 };
const result = objectSpread(target, { name: "Alice" }, { active: true });
console.log(result); // { id: 1, name: "Alice", active: true }
console.log(target === result); // true (modified in-place)

Configuration Merging:

import { objectSpread, objectCopy } from "@polkadot/util";

// Merge configuration objects
function createConfig(userConfig: Partial<Config> = {}): Config {
  const defaultConfig = {
    apiUrl: "https://api.example.com",
    timeout: 5000,
    retries: 3,
    debug: false
  };
  
  return objectSpread(objectCopy(defaultConfig), userConfig);
}

interface Config {
  apiUrl: string;
  timeout: number;
  retries: number;
  debug: boolean;
}

const config1 = createConfig(); // Uses all defaults
const config2 = createConfig({ debug: true, timeout: 10000 }); // Override specific values

console.log(config1.debug); // false
console.log(config2.debug); // true
console.log(config2.apiUrl); // "https://api.example.com" (from defaults)

Object Clearing:

import { objectClear } from "@polkadot/util";

// Clear object while preserving reference
const cache = { user123: { name: "Alice" }, user456: { name: "Bob" } };
const originalRef = cache;

objectClear(cache);
console.log(cache); // {}
console.log(originalRef === cache); // true (same reference)

// Useful for resetting state
class StateManager {
  private state: Record<string, unknown> = {};
  
  setState(newState: Record<string, unknown>) {
    objectClear(this.state);
    objectSpread(this.state, newState);
  }
  
  clearState() {
    objectClear(this.state);
  }
  
  getState() {
    return this.state;
  }
}

Property Introspection:

import { objectProperties, objectProperty } from "@polkadot/util";

class Example {
  public name = "test";
  private _id = 123;
  
  get id() { return this._id; }
  set id(value: number) { this._id = value; }
  
  method() { return "hello"; }
}

const instance = new Example();

// Get all property descriptors
const allProps = objectProperties(instance);
console.log(Object.keys(allProps)); // ["name", "_id", "id", "method", ...]

// Get specific property descriptor
const nameDesc = objectProperty(instance, "name");
console.log(nameDesc?.writable); // true
console.log(nameDesc?.enumerable); // true

const idDesc = objectProperty(instance, "id");
console.log(idDesc?.get); // [Function: get id]
console.log(idDesc?.set); // [Function: set id]

// Check if property is configurable
function isConfigurableProperty(obj: Record<string, unknown>, prop: string): boolean {
  const desc = objectProperty(obj, prop);
  return desc?.configurable === true;
}

Data Transformation Pipeline:

import { objectEntries, objectKeys, objectSpread } from "@polkadot/util";

// Transform object keys and values
function transformObject<T extends Record<string, unknown>>(
  obj: T,
  keyTransform: (key: string) => string,
  valueTransform: (value: unknown, key: string) => unknown
): Record<string, unknown> {
  return Object.fromEntries(
    objectEntries(obj).map(([key, value]) => [
      keyTransform(String(key)),
      valueTransform(value, String(key))
    ])
  );
}

// Example: Convert API response to internal format
const apiResponse = {
  "user_id": "123",
  "full_name": "John Doe",
  "email_address": "john@example.com",
  "is_active": "true",
  "created_at": "2023-01-01T00:00:00Z"
};

const internal = transformObject(
  apiResponse,
  key => key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()), // snake_case to camelCase
  (value, key) => {
    if (key.includes('is_') && typeof value === 'string') {
      return value === 'true'; // Convert string booleans
    }
    if (key.includes('_at') && typeof value === 'string') {
      return new Date(value); // Convert date strings
    }
    return value;
  }
);

console.log(internal);
// {
//   userId: "123",
//   fullName: "John Doe", 
//   emailAddress: "john@example.com",
//   isActive: true,
//   createdAt: Date object
// }

Object Validation:

import { objectKeys, objectEntries } from "@polkadot/util";

// Validate object structure
function validateObjectStructure<T extends Record<string, unknown>>(
  obj: unknown,
  requiredKeys: (keyof T)[],
  optionalKeys: (keyof T)[] = []
): obj is T {
  if (!obj || typeof obj !== 'object') return false;
  
  const keys = objectKeys(obj as Record<string, unknown>);
  const allowedKeys = [...requiredKeys, ...optionalKeys];
  
  // Check all required keys exist
  const hasAllRequired = requiredKeys.every(key => keys.includes(key as string));
  
  // Check no extra keys exist
  const hasOnlyAllowed = keys.every(key => allowedKeys.includes(key as keyof T));
  
  return hasAllRequired && hasOnlyAllowed;
}

interface User {
  id: number;
  name: string;
  email?: string;
}

const validUser = { id: 123, name: "Alice", email: "alice@example.com" };
const invalidUser = { id: 123, extra: "field" }; // Missing required 'name'

console.log(validateObjectStructure<User>(validUser, ['id', 'name'], ['email'])); // true
console.log(validateObjectStructure<User>(invalidUser, ['id', 'name'], ['email'])); // false

Install with Tessl CLI

npx tessl i tessl/npm-polkadot--util

docs

arrays.md

big-numbers.md

compact.md

data-conversion.md

formatting.md

index.md

objects.md

strings.md

system.md

type-checking.md

tile.json