@ace-riders/js-toolkit
v0.1.2
Published
This package contains a growing collection of utility functions and helpers designed to streamline development across projects within **Asseco Central Europe**. Its purpose is to consolidate common logic, patterns, and tools that we use repeatedly — to pr
Readme
🧰 Asseco Utilities Toolkit
This package contains a growing collection of utility functions and helpers designed to streamline development across projects within Asseco Central Europe. Its purpose is to consolidate common logic, patterns, and tools that we use repeatedly — to promote consistency, reduce duplication, and speed up delivery.
Whether it's a data transformation, safe type guards, object utilities, or runtime helpers, this toolkit is maintained with internal use in mind — but is built to be modular and extensible.
Contributions are welcome!
If you have suggestions, bugfixes, or want to integrate new features, feel free to open a pull request or reach out directly.
Helpers
🧩 has
A lightweight, type-safe helper to check whether an object contains a given property — with proper TypeScript narrowing.
Unlike using prop in obj, this approach retains value type safety and supports type guards, allowing downstream code to safely access the property.
🧠 Why use has()?
- Avoids pitfalls of in operator and optional chaining when type safety matters
- Ensures that TypeScript narrows the type after the check
- Uses
Object.prototype.hasOwnProperty.callinternally, which is the safest approach (even for objects with shadowed or missing hasOwnProperty)
📦 Example
type User = {
id: number;
name?: string;
}
const data: unknown = { id: 42 };
if (has<"id", number, typeof data>("id", data)) {
// `data` is now narrowed to: { id: number }
console.log(data.id); // ✅ Safe access
}You can optionally omit the type parameters when inference is enough:
if (has("name", user)) {
console.log(user.name.toUpperCase()); // ✅ No "possibly undefined" warning
}🛠 Use Cases
- Runtime property checks while retaining static type guarantees
- Safe handling of dynamic objects or external data (e.g. from APIs)
- Type refinement in utility functions, guards, or transforms
🧩 is
The is() function is a narrowing type guard that filters out undefined and null, helping you ensure that a value is defined and non-null.
This is especially useful when working with optional values, functional filtering, or mapping operations where TypeScript loses precision.
📦 Example
const maybeName: string | undefined | null = getName();
if (is(maybeName)) {
// maybeName is now type string
console.log(maybeName.toUpperCase());
}🛠 Use Cases
- Filtering arrays with optional or nullable items
- Safe navigation with optional chaining results
- Transforming nullable data
🧩 isObject
The isObject() function checks whether a given value is of type "object" — helping distinguish objects from primitives in a type-safe way.
This is especially useful when working with unknown or external data (e.g., from APIs or untyped inputs), where you need to guard before accessing properties.
📦 Example
const maybe = JSON.parse(data);
if (isObject(maybe)) {
// Safe to access properties
console.log(maybe["id"]);
}⚠️ Important Notes
This function does not exclude null, which is also of type "object" in JavaScript. In this case, you can use isSafeObject function.
🛠 Use Cases
- Validating dynamic data
- Type guards before deep access
- Parsing JSON or query strings
🧩 isString
The isString() function is a type guard that checks whether a given value is a non-null, non-undefined string.
It builds upon the is() helper to safely handle unknown or nullable inputs, and ensures strict type narrowing to string.
📦 Example
const input: unknown = "Hello";
if (isString(input)) {
// input is now typed as string
console.log(input.toUpperCase());
}🛠 Use Cases
- Validating external input
- Filtering mixed arrays
- Guarding before string-specific logic
🧩 isNumber
The isNumber() function is a type guard that checks whether a given value is a defined, non-null number.
It extends the is() helper and ensures safe type narrowing, especially useful when working with dynamic or unknown inputs.
📦 Example
const value = form.get("age");
if (isNumber(value)) {
console.log("Age in months:", value * 12);
}🛠 Use Cases
- Validating numeric input
- Filtering data arrays
- Enforcing numeric logic
🧩 omit
The omit() function creates a shallow copy of an object excluding a specified list of keys.
This is the counterpart to pick() and is useful when you want to keep “everything else” except certain properties.
📦 Example
const user = {
id: 1,
name: "Alice",
password: "secret",
email: "[email protected]",
};
const safeUser = omit(user, ["password"]);
// => { id: 1, name: "Alice", email: "[email protected]" }
type SafeUser = typeof safeUser;
// type SafeUser = { id: number; name: string; email: string }🛠 Use Cases
- Removing sensitive data
- UI state shaping
- Cleaning API payloads
- Composing objects dynamically
- Selective serialization
🧩 pick
The pick() function allows you to create a shallow copy of an object containing only a specified subset of its keys.
It’s a type-safe way to extract relevant properties from a larger object, commonly used in data transformation, serialization, or sanitization layers.
📦 Example
const user = {
id: 1,
name: "Alice",
email: "[email protected]",
role: "admin"
}
const publicData = pick(user, ["id", "name"]);
// => { id: 1, name: "Alice" }
type PublicUser = typeof publicData;
// type PublicUser = { id: number; name: string }🛠 Use Cases
- Select only relevant data to expose (e.g., from user object)
- Prepare objects for transmission or logging
- Normalize partial data in reducers or state transformations
⚠️ Notes
- This implementation is shallow — it is not deep clone values.
- It uses
Object.entries()internally, which skips inherited properties (safe for plain objects). - The as
Pick<T, K>cast ensures proper typing even with runtime filtering.
🧩 property
The property() helper is a safe property accessor that attempts to retrieve a value by key, returning undefined if the property does not exist — with type safety.
It builds upon the has() function to avoid potential runtime errors when working with unknown or dynamic objects while preserving TypeScript’s inference.
📦 Example
const user = {
id: 1,
name: "Alice",
age: 30,
}
const age = property("age", user);
// => 30
const role = property("role", user);
// => undefinedBecause the check uses has(), the function respects actual object ownership and avoids inherited or prototype properties.
🛠 Use Cases
- Safe access without optional chaining
- Dynamic property lookups
- Graceful fallbacks
- Combine with has() for manual guards
🧩 tryDo / tryDoAsync
A lightweight utility to handle success and error states in a type-safe and consistent way, inspired by the Result type in languages like Rust.
These helpers provide a unified approach to managing operations that may fail while avoiding exceptions and promoting explicit handling of errors.
✅ Features
- Strongly typed
Result<T, E>structure - Helper functions
ok()anderr()for creating results - Synchronous
tryDo()wrapper - Asynchronous
tryDoAsync()wrapper - Compatible with any
Errorsubtype
💡 Example
Safely executes a synchronous function and returns a Result.
const result = tryDo(() => JSON.parse("not json"));
if (result.ok) {
console.log("Success:", result.value);
} else {
console.error("Parsing failed:", result.error.message);
}Safely executes an asynchronous function and returns a Promise<Result>.
const result = await tryDoAsync(() => fetch("/api/data").then(res => res.json()));
if (result.ok) {
console.log("Data:", result.value);
} else {
console.error("API call failed:", result.error.message);
}📦 Use Cases
- Replace try/catch blocks with a functional API
- Normalize error handling across sync/async logic
- Improve clarity in services, utilities, or data fetchers
Utility Types
A set of common type utilities that help improve expressiveness and type safety across TypeScript codebases.
🔹 Optional
Represents a value that may or may not be defined. Useful for optional function parameters, config fields, or partial values.
🔹 Nullable
Represents a value that can explicitly be null. Useful when modeling values from external APIs or legacy systems that use null as a placeholder.
🔹 OptionalProperty<T, K>
Makes only a subset of properties (K) optional in a given type T. Useful for selectively loosening type requirements, e.g. in partial form updates or patch requests.
Example
type User = { id: string; name: string; age: number }
type PartialName = OptionalProperty<User, "name">
// => { name?: string; id: string; age: number }🔹 ValueOf
Extracts a union of all value types in an object type T. Useful for working with enums, maps, or records.
Example
type Colors = { primary: "red"; secondary: "blue" }
type ColorValues = ValueOf<Colors>
// => "red" | "blue"