Utility Functions & TypeScript Types
August 18, 2025 ยท View on GitHub
This guide covers the general utility functions and TypeScript helper types for common development tasks.
Object Utilities
cleanNullishFromObject
Removes null and undefined values from an object, useful for cleaning query parameters before API calls.
import { cleanNullishFromObject } from 'ngx-primeng-toolkit';
// Basic usage
const queryParams = {
name: 'John',
age: null,
status: 'active',
department: undefined,
email: ''
};
const cleaned = cleanNullishFromObject(queryParams);
// Result: { name: 'John', status: 'active', email: '' }
// With array values
const filters = {
categories: ['tech', 'business'],
tags: null,
active: true,
archived: undefined
};
const cleanedFilters = cleanNullishFromObject(filters);
// Result: { categories: ['tech', 'business'], active: true }
Practical Usage Examples
// In API service for cleaning query parameters
export class ApiService {
searchUsers(filters: UserSearchFilters) {
const cleanFilters = cleanNullishFromObject(filters);
return this.http.get('/api/users', { params: cleanFilters });
}
}
// In component for form data
export class UserSearchComponent {
searchForm = new FormGroup({
name: new FormControl(''),
department: new FormControl(null),
status: new FormControl(null),
startDate: new FormControl(null)
});
search() {
const formData = this.searchForm.value;
const cleanData = cleanNullishFromObject(formData);
// Only sends non-null/undefined values to API
this.userService.searchUsers(cleanData);
}
}
// In table state helper integration
export class UserTableComponent {
applyFilters() {
const filters = {
department: this.selectedDepartment,
status: this.selectedStatus,
dateRange: this.dateFilter // might be null
};
const cleanFilters = cleanNullishFromObject(filters);
this.tableState.patchQueryParams(cleanFilters);
}
}
TypeScript Utility Types
The library provides several utility types for handling nullable and partial types:
RecursiveNullable
Makes all properties of a type nullable (T | null):
import { RecursiveNullable } from 'ngx-primeng-toolkit';
type User = {
id: number;
name: string;
email: string;
profile: {
age: number;
bio: string;
};
};
type NullableUser = RecursiveNullable<User>;
// Result: {
// id: number | null;
// name: string | null;
// email: string | null;
// profile: {
// age: number | null;
// bio: string | null;
// } | null;
// }
// Practical usage in form models
export class UserFormComponent {
// Form model that allows null values
userForm: FormGroup<{
name: FormControl<string | null>;
email: FormControl<string | null>;
profile: FormGroup<{
age: FormControl<number | null>;
bio: FormControl<string | null>;
}>;
}>;
// Default form state with nulls
defaultUser: RecursiveNullable<User> = {
id: null,
name: null,
email: null,
profile: {
age: null,
bio: null
}
};
resetForm() {
this.userForm.patchValue(this.defaultUser);
}
}
Nullish
Represents a value that can be null or undefined:
import { Nullish } from 'ngx-primeng-toolkit';
type MaybeString = Nullish<string>; // string | null | undefined
type MaybeUser = Nullish<User>; // User | null | undefined
// Useful for optional service responses
export class UserService {
getCurrentUser(): Observable<Nullish<User>> {
return this.http.get<User>('/api/user/current')
.pipe(
catchError(() => of(null))
);
}
findUser(id: number): Promise<Nullish<User>> {
return this.http.get<User>(`/api/users/${id}`)
.pipe(
catchError(() => of(undefined))
)
.toPromise();
}
}
// In components
export class UserProfileComponent {
currentUser: Nullish<User> = null;
async loadUser() {
this.currentUser = await this.userService.getCurrentUser();
// Type-safe null checking
if (this.currentUser) {
console.log(`Welcome ${this.currentUser.name}`);
}
}
}
RecursiveNullish
Makes all properties nullish (T | null | undefined) recursively:
import { RecursiveNullish } from 'ngx-primeng-toolkit';
type User = {
id: number;
profile: {
name: string;
age: number;
};
settings: {
theme: string;
notifications: boolean;
};
};
type NullishUser = RecursiveNullish<User>;
// Result: {
// id: number | null | undefined;
// profile: {
// name: string | null | undefined;
// age: number | null | undefined;
// } | null | undefined;
// settings: {
// theme: string | null | undefined;
// notifications: boolean | null | undefined;
// } | null | undefined;
// }
// Useful for deeply nullable form states
export interface FormState extends RecursiveNullish<User> {}
export class UserFormComponent {
formState: FormState = {
id: undefined,
profile: {
name: null,
age: undefined
},
settings: null
};
// Type-safe form reset
resetForm() {
this.formState = {
id: undefined,
profile: undefined,
settings: undefined
};
}
}
RecursivePartial
Makes all properties optional recursively:
import { RecursivePartial } from 'ngx-primeng-toolkit';
type User = {
id: number;
name: string;
profile: {
age: number;
bio: string;
};
settings: {
theme: string;
notifications: boolean;
};
};
type PartialUser = RecursivePartial<User>;
// Result: {
// id?: number;
// name?: string;
// profile?: {
// age?: number;
// bio?: string;
// };
// settings?: {
// theme?: string;
// notifications?: boolean;
// };
// }
// Perfect for update operations
export class UserService {
updateUser(id: number, updates: RecursivePartial<User>) {
return this.http.patch(`/api/users/${id}`, updates);
}
updateUserProfile(id: number, profileUpdates: RecursivePartial<User['profile']>) {
return this.http.patch(`/api/users/${id}/profile`, profileUpdates);
}
}
// Usage in components
export class UserProfileComponent {
updateProfile() {
// Only send changed fields
const updates: RecursivePartial<User> = {
profile: {
age: this.newAge, // Only age is being updated
// bio is omitted, won't be sent to API
}
// Other fields omitted, won't be updated
};
this.userService.updateUser(this.userId, updates);
}
updateSettings() {
const settingsUpdate: RecursivePartial<User> = {
settings: {
theme: 'dark' // Only update theme
// notifications is omitted
}
};
this.userService.updateUser(this.userId, settingsUpdate);
}
}
Combining Utilities
These utilities work great together for complex form and API scenarios:
import {
cleanNullishFromObject,
RecursiveNullish,
RecursivePartial
} from 'ngx-primeng-toolkit';
export class AdvancedFormComponent {
// Form model with nullable fields
formData: RecursiveNullish<User> = {
id: null,
name: null,
email: null,
profile: {
age: null,
bio: null
}
};
// Update model with partial data
updatePartial(updates: RecursivePartial<User>) {
// Merge updates into form data
this.formData = { ...this.formData, ...updates };
}
// Submit form with cleaned data
async submitForm() {
// Remove null/undefined values before API call
const cleanData = cleanNullishFromObject(this.formData);
try {
await this.userService.updateUser(cleanData);
this.showSuccess('User updated successfully');
} catch (error) {
this.showError('Failed to update user');
}
}
// Reset form to nullable defaults
resetForm() {
this.formData = {
id: null,
name: null,
email: null,
profile: null
};
}
}
Advanced Usage Examples
API Query Builder
export class ApiQueryBuilder {
private filters: RecursiveNullish<any> = {};
setFilter<T>(key: string, value: Nullish<T>) {
this.filters[key] = value;
return this;
}
build(): Record<string, any> {
return cleanNullishFromObject(this.filters);
}
reset() {
this.filters = {};
return this;
}
}
// Usage
const queryBuilder = new ApiQueryBuilder()
.setFilter('name', 'John')
.setFilter('department', null) // Will be removed
.setFilter('active', true)
.setFilter('startDate', undefined); // Will be removed
const cleanQuery = queryBuilder.build();
// Result: { name: 'John', active: true }
Form Data Processor
export class FormDataProcessor<T> {
static processFormData<T>(
formValue: RecursiveNullish<T>,
options: {
removeNullish?: boolean;
defaultValues?: RecursivePartial<T>;
} = {}
): RecursivePartial<T> {
let processed = { ...formValue };
// Apply default values
if (options.defaultValues) {
processed = { ...options.defaultValues, ...processed };
}
// Remove null/undefined if requested
if (options.removeNullish) {
processed = cleanNullishFromObject(processed);
}
return processed;
}
}
// Usage in component
export class UserFormComponent {
submitForm() {
const processedData = FormDataProcessor.processFormData(
this.userForm.value,
{
removeNullish: true,
defaultValues: {
settings: {
theme: 'light'
}
}
}
);
this.userService.createUser(processedData);
}
}
Best Practices
Type Safety
// Good: Use specific utility types for different scenarios
interface CreateUserRequest extends RecursivePartial<User> {}
interface UpdateUserRequest extends RecursivePartial<User> {}
interface UserFormState extends RecursiveNullish<User> {}
// Good: Combine utilities for complex scenarios
function processApiData<T>(data: RecursiveNullish<T>): RecursivePartial<T> {
return cleanNullishFromObject(data);
}
Performance Considerations
// Good: Clean data before API calls to reduce payload size
const cleanPayload = cleanNullishFromObject(formData);
this.http.post('/api/users', cleanPayload);
// Good: Use utility types to prevent unnecessary data in requests
interface UserUpdatePayload extends RecursivePartial<Pick<User, 'name' | 'email'>> {}
Form Integration
// Good: Use utility types for form models
export class FormComponent {
private formModel: RecursiveNullish<User> = {};
updateForm(updates: RecursivePartial<User>) {
Object.assign(this.formModel, updates);
}
getCleanFormData(): RecursivePartial<User> {
return cleanNullishFromObject(this.formModel);
}
}