sortObjectKeys
Reorders object properties according to a specified key sequence with optional filtering. Creates a new object with properties arranged in the order specified by the keys array, followed by any remaining properties in their original order. Supports flexible undefined filtering options and maintains type safety while providing flexible property organization for consistent object structures and serialization.
Signature
const sortObjectKeys: <Dict extends Dictionary>(object: Dict | Nullish, keys: string[], options?: {
ignoreUndefinedKey?: boolean;
ignoreUndefinedValue?: boolean;
}) => Dict
Parameters
| Name | Type | Description |
|---|---|---|
object | - | Source object to reorder (null/undefined returns empty object) |
keys | - | Array defining the desired property order |
options | - | Optional configuration object |
Returns
New object with properties ordered according to keys array
Examples
Basic property ordering
import { sortObjectKeys } from '@winglet/common-utils';
// Reorder object properties
const user = { email: 'john@example.com', name: 'John', id: 123, active: true };
const ordered = sortObjectKeys(user, ['id', 'name', 'email', 'active']);
console.log(ordered); // { id: 123, name: 'John', email: 'john@example.com', active: true }
// Partial ordering - specified keys first, others follow
const partialOrder = sortObjectKeys(user, ['name', 'id']);
console.log(partialOrder); // { name: 'John', id: 123, email: 'john@example.com', active: true }
API response standardization
// Standardize API response structure
const apiData = {
metadata: { version: '1.0', timestamp: '2023-01-01' },
data: { users: [...], count: 42 },
status: 'success',
message: 'Data retrieved successfully'
};
// Ensure consistent property order
const standardOrder = ['status', 'message', 'data', 'metadata'];
const standardized = sortObjectKeys(apiData, standardOrder);
console.log(Object.keys(standardized)); // ['status', 'message', 'data', 'metadata']
Undefined value filtering
const incompleteData = {
id: 1,
name: 'Alice',
email: undefined, // Missing email
phone: '+1234567890',
address: undefined, // Missing address
active: true
};
// Order with undefined values included
const withUndefined = sortObjectKeys(
incompleteData,
['id', 'name', 'email', 'phone']
);
console.log(withUndefined);
// { id: 1, name: 'Alice', email: undefined, phone: '+1234567890', address: undefined, active: true }
// Order with undefined values filtered out
const filtered = sortObjectKeys(
incompleteData,
['id', 'name', 'email', 'phone'],
{ ignoreUndefinedValue: true }
);
console.log(filtered);
// { id: 1, name: 'Alice', phone: '+1234567890', active: true }
Configuration object organization
// Organize configuration with priority ordering
const config = {
timeout: 5000,
retries: 3,
apiUrl: 'https://api.example.com',
debug: false,
version: '2.1.0',
environment: 'production'
};
// Critical settings first, then others
const priorityOrder = ['environment', 'version', 'apiUrl', 'timeout', 'retries'];
const organized = sortObjectKeys(config, priorityOrder);
console.log(Object.keys(organized));
// ['environment', 'version', 'apiUrl', 'timeout', 'retries', 'debug']
Form field organization
// Organize form data for consistent display
const formData = {
newsletter: true,
country: 'USA',
firstName: 'John',
lastName: 'Doe',
email: 'john@example.com',
phone: undefined, // Optional field
city: 'New York',
zipCode: '10001'
};
// Logical field order for forms
const fieldOrder = [
'firstName', 'lastName', 'email', 'phone',
'city', 'zipCode', 'country', 'newsletter'
];
const orderedForm = sortObjectKeys(formData, fieldOrder, {
ignoreUndefinedValue: true
});
console.log(orderedForm);
// {
// firstName: 'John',
// lastName: 'Doe',
// email: 'john@example.com',
// city: 'New York',
// zipCode: '10001',
// country: 'USA',
// newsletter: true
// }
Database record normalization
// Normalize database records for consistent output
const dbRecord = {
updated_at: '2023-01-02T10:30:00Z',
data: { content: 'Record content' },
created_at: '2023-01-01T09:00:00Z',
id: 'record_123',
status: 'active',
version: 1
};
// Standard record structure
const recordOrder = ['id', 'status', 'version', 'created_at', 'updated_at'];
const normalized = sortObjectKeys(dbRecord, recordOrder);
console.log(Object.keys(normalized));
// ['id', 'status', 'version', 'created_at', 'updated_at', 'data']
Handling edge cases
// Empty and null objects
console.log(sortObjectKeys(null, ['a', 'b'])); // {}
console.log(sortObjectKeys(undefined, ['a', 'b'])); // {}
console.log(sortObjectKeys({}, ['a', 'b'])); // {}
// Non-existent keys in order array
const obj = { x: 1, y: 2 };
const withNonExistent = sortObjectKeys(obj, ['a', 'x', 'b', 'y', 'c']);
console.log(withNonExistent); // { x: 1, y: 2 } (only existing keys included)
// Only include specific keys (ignoreUndefinedKey)
const data = { a: 1, b: 2, c: 3, d: 4, e: 5 };
const onlySpecified = sortObjectKeys(data, ['c', 'a'], {
ignoreUndefinedKey: true
});
console.log(onlySpecified); // { c: 3, a: 1 } (only keys in array)
// Objects with mixed undefined values
const mixed = { a: 1, b: undefined, c: 3, d: undefined, e: 5 };
const cleanOrdered = sortObjectKeys(mixed, ['e', 'c', 'a'], {
ignoreUndefinedValue: true
});
console.log(cleanOrdered); // { e: 5, c: 3, a: 1 }
// Combine both options
const complex = { a: 1, b: undefined, c: 3, d: 4, e: undefined };
const filtered = sortObjectKeys(complex, ['c', 'b', 'a'], {
ignoreUndefinedKey: true,
ignoreUndefinedValue: true
});
console.log(filtered); // { c: 3, a: 1 } (only specified keys, excluding undefined)
JSON serialization preparation
// Prepare objects for consistent JSON output
const responseData = {
pagination: { page: 1, limit: 20, total: 100 },
timestamp: Date.now(),
data: [{ id: 1, name: 'Item 1' }],
success: true,
errors: undefined // Sometimes present
};
// Standard API response order
const apiOrder = ['success', 'data', 'pagination', 'timestamp', 'errors'];
const prepared = sortObjectKeys(responseData, apiOrder, {
ignoreUndefinedValue: true
});
console.log(JSON.stringify(prepared, null, 2));
// {
// "success": true,
// "data": [{ "id": 1, "name": "Item 1" }],
// "pagination": { "page": 1, "limit": 20, "total": 100 },
// "timestamp": 1640995200000
// }
Playground
import { sortObjectKeys } from '@winglet/common-utils'; // Reorder object properties const user = { email: 'john@example.com', name: 'John', id: 123, active: true }; const ordered = sortObjectKeys(user, ['id', 'name', 'email', 'active']); console.log(ordered); // { id: 123, name: 'John', email: 'john@example.com', active: true } // Partial ordering - specified keys first, others follow const partialOrder = sortObjectKeys(user, ['name', 'id']); console.log(partialOrder); // { name: 'John', id: 123, email: 'john@example.com', active: true }
Notes
Ordering Strategy:
- Primary Order: Properties appear in the sequence specified by keys array
- Secondary Order: Remaining properties follow in their original enumeration order
- Missing Keys: Keys in the order array that don't exist in the object are skipped
- Extra Properties: Properties not in the order array are appended at the end (unless ignoreUndefinedKey is true)
Filtering Behavior:
- ignoreUndefinedKey: When true, only properties in keys array are included (remaining properties excluded)
- ignoreUndefinedValue: When true, properties with undefined values are excluded
- Default behavior: All properties included, ordered properties first then remaining ones
- Filtering Priority: Applied during both ordered and remaining property processing
Performance Characteristics:
- Time Complexity: O(n + m) where n is object size, m is keys array length
- Space Complexity: O(n) for the new object
- Memory: Creates new object, preserves original object unchanged
Type Safety:
- Maintains original object type through generic constraints
- Preserves property value types after reordering
- Keys array accepts any string values (non-existent keys ignored)
- Return type matches input dictionary type
Use Cases:
- API response structure standardization
- Form field organization and display order
- Configuration object normalization
- Database record formatting
- JSON serialization preparation
- Object property priority management
Limitations:
- Only reorders enumerable own properties
- Does not handle Symbol keys
- String keys only in the ordering array
- Undefined filtering options are independent and can be combined
- Original object structure is not preserved if circular references exist