Enhanced array and enumerable interfaces with change tracking and computed properties for reactive data management.
Enhanced array interface with observable properties and computed capabilities.
/**
* Enhanced array interface with observable properties and computed capabilities
*/
interface EmberArray extends Array<any> {
/**
* Get property value with support for array-specific properties
* @param key - Property key (can be array index or property name)
* @returns Property value
*/
get(key: string | number): any;
/**
* Set property value and notify observers
* @param key - Property key
* @param value - Value to set
* @returns The value that was set
*/
set(key: string | number, value: any): any;
/**
* Add object to end of array
* @param item - Item to add
* @returns The added item
*/
pushObject(item: any): any;
/**
* Add multiple objects to end of array
* @param items - Items to add
* @returns The array
*/
pushObjects(items: any[]): EmberArray;
/**
* Remove object from array
* @param item - Item to remove
* @returns The removed item or null
*/
removeObject(item: any): any;
/**
* Remove multiple objects from array
* @param items - Items to remove
* @returns The array
*/
removeObjects(items: any[]): EmberArray;
/**
* Insert object at specific index
* @param index - Index to insert at
* @param item - Item to insert
* @returns The array
*/
insertAt(index: number, item: any): EmberArray;
/**
* Remove object at specific index
* @param index - Index to remove from
* @returns The removed item
*/
removeAt(index: number): any;
/**
* Find first object matching property value
* @param key - Property key to match
* @param value - Value to match
* @returns First matching object or undefined
*/
findBy(key: string, value: any): any;
/**
* Filter objects by property value
* @param key - Property key to match
* @param value - Value to match
* @returns Array of matching objects
*/
filterBy(key: string, value: any): any[];
/**
* Map array to property values
* @param key - Property key to extract
* @returns Array of property values
*/
mapBy(key: string): any[];
/**
* Sort array by property
* @param key - Property key to sort by
* @returns New sorted array
*/
sortBy(key: string): any[];
/**
* Get unique values by property
* @param key - Property key for uniqueness
* @returns Array with unique values
*/
uniqBy(key: string): any[];
/**
* Check if array contains object
* @param item - Item to check for
* @returns Whether array contains item
*/
includes(item: any): boolean;
/** First object in array */
readonly firstObject: any;
/** Last object in array */
readonly lastObject: any;
/** Array length */
readonly length: number;
}Interface for arrays that can be modified with change notifications.
/**
* Interface for arrays that can be modified with change notifications
*/
interface MutableArray extends EmberArray {
/**
* Add object to array if not already present
* @param item - Item to add
* @returns The array
*/
addObject(item: any): MutableArray;
/**
* Add multiple objects to array, skipping duplicates
* @param items - Items to add
* @returns The array
*/
addObjects(items: any[]): MutableArray;
/**
* Replace portion of array with new objects
* @param start - Starting index
* @param deleteCount - Number of items to delete
* @param items - Items to insert
* @returns Array of removed items
*/
replace(start: number, deleteCount: number, items: any[]): any[];
/**
* Clear all objects from array
* @returns The empty array
*/
clear(): MutableArray;
/**
* Reverse array in place
* @returns The reversed array
*/
reverseObjects(): MutableArray;
/**
* Remove all instances of objects
* @param items - Items to remove
* @returns The array
*/
removeObjects(items: any[]): MutableArray;
}Proxy class that provides array interface for underlying content.
/**
* Proxy class that provides array interface for underlying content
*/
class ArrayProxy extends EmberObject implements MutableArray {
/**
* Create ArrayProxy instance
* @param properties - Initial properties including content
* @returns ArrayProxy instance
*/
static create(properties?: { content?: any[] }): ArrayProxy;
/** Underlying array content */
content: any[];
/** Whether array is arranged (sorted/filtered) */
isArranged: boolean;
/**
* Get object at index
* @param index - Array index
* @returns Object at index
*/
objectAt(index: number): any;
/**
* Get objects at multiple indexes
* @param indexes - Array of indexes
* @returns Array of objects
*/
objectsAt(indexes: number[]): any[];
// Implements all EmberArray and MutableArray methods
pushObject(item: any): any;
removeObject(item: any): any;
findBy(key: string, value: any): any;
// ... (inherits all array methods)
}Functions for creating and working with Ember arrays.
/**
* Create Ember array from regular array or array-like object
* @param array - Array or array-like object to convert
* @returns EmberArray instance
*/
function A(array?: any[]): EmberArray;
/**
* Check if object is array or array-like
* @param obj - Object to test
* @returns Whether object is array-like
*/
function isArray(obj: any): boolean;
/**
* Convert value to array
* @param obj - Value to convert to array
* @returns Array containing the value(s)
*/
function makeArray(obj: any): any[];Usage Examples:
import { A } from "@ember/array";
import ArrayProxy from "@ember/array/proxy";
// Create Ember array
const users = A([
{ name: 'Alice', role: 'admin', active: true },
{ name: 'Bob', role: 'user', active: false },
{ name: 'Charlie', role: 'admin', active: true }
]);
// Array methods with change tracking
users.pushObject({ name: 'Diana', role: 'user', active: true });
users.removeObject(users.findBy('name', 'Bob'));
// Query methods
const admins = users.filterBy('role', 'admin');
const activeUsers = users.filterBy('active', true);
const names = users.mapBy('name');
const firstAdmin = users.findBy('role', 'admin');
console.log(admins.length); // 2
console.log(names); // ['Alice', 'Charlie', 'Diana']
// Array proxy for computed arrays
const UserListProxy = ArrayProxy.extend({
content: users,
activeUsers: computed('content.@each.active', function() {
return this.content.filterBy('active', true);
}),
adminCount: computed('content.@each.role', function() {
return this.content.filterBy('role', 'admin').length;
})
});
const userList = UserListProxy.create();
console.log(userList.get('activeUsers.length')); // 3
console.log(userList.get('adminCount')); // 2Base interface for collections that can be enumerated.
/**
* Base interface for collections that can be enumerated
*/
interface Enumerable {
/**
* Iterate over all objects in collection
* @param callback - Function called for each object
* @param target - Context for callback
* @returns The enumerable
*/
forEach(callback: (item: any, index: number) => void, target?: any): Enumerable;
/**
* Map collection to new values
* @param callback - Mapping function
* @param target - Context for callback
* @returns Array of mapped values
*/
map(callback: (item: any, index: number) => any, target?: any): any[];
/**
* Filter collection by predicate
* @param callback - Filter predicate
* @param target - Context for callback
* @returns Filtered array
*/
filter(callback: (item: any, index: number) => boolean, target?: any): any[];
/**
* Find first matching object
* @param callback - Search predicate
* @param target - Context for callback
* @returns First matching object or undefined
*/
find(callback: (item: any, index: number) => boolean, target?: any): any;
/**
* Check if any object matches predicate
* @param callback - Test predicate
* @param target - Context for callback
* @returns Whether any object matches
*/
any(callback: (item: any, index: number) => boolean, target?: any): boolean;
/**
* Check if all objects match predicate
* @param callback - Test predicate
* @param target - Context for callback
* @returns Whether all objects match
*/
every(callback: (item: any, index: number) => boolean, target?: any): boolean;
/**
* Reduce collection to single value
* @param callback - Reducer function
* @param initialValue - Initial value for reduction
* @param target - Context for callback
* @returns Reduced value
*/
reduce(callback: (previousValue: any, item: any, index: number) => any, initialValue?: any, target?: any): any;
/**
* Convert enumerable to array
* @returns Array representation
*/
toArray(): any[];
}Interface for enumerables that can be modified.
/**
* Interface for enumerables that can be modified
*/
interface MutableEnumerable extends Enumerable {
/**
* Add object to enumerable
* @param item - Object to add
* @returns The enumerable
*/
addObject(item: any): MutableEnumerable;
/**
* Remove object from enumerable
* @param item - Object to remove
* @returns The enumerable
*/
removeObject(item: any): MutableEnumerable;
}Usage Examples:
import EmberObject from "@ember/object";
import { A } from "@ember/array";
// Working with enumerable collections
const Collection = EmberObject.extend({
items: null,
init() {
this._super(...arguments);
this.items = A([]);
},
activeItems: computed('items.@each.active', function() {
return this.items.filterBy('active', true);
}),
hasActiveItems: computed('activeItems.length', function() {
return this.activeItems.length > 0;
}),
totalValue: computed('items.@each.value', function() {
return this.items.reduce((sum, item) => sum + (item.value || 0), 0);
})
});
const collection = Collection.create();
collection.items.pushObjects([
{ name: 'Item 1', active: true, value: 10 },
{ name: 'Item 2', active: false, value: 20 },
{ name: 'Item 3', active: true, value: 15 }
]);
console.log(collection.get('activeItems.length')); // 2
console.log(collection.get('totalValue')); // 45interface ArrayLike {
/** Array length */
length: number;
/** Index access */
[index: number]: any;
}
interface ArrayObserver {
/** Called when array changes */
arrayWillChange?(array: EmberArray, start: number, removeCount: number, addCount: number): void;
/** Called after array changes */
arrayDidChange?(array: EmberArray, start: number, removeCount: number, addCount: number): void;
}
interface SortDescriptor {
/** Property to sort by */
property: string;
/** Sort direction */
direction: 'asc' | 'desc';
}