From 80ef0c8a0f3df0db96687b778afa97f8ee12491e Mon Sep 17 00:00:00 2001 From: Mike North Date: Thu, 20 Sep 2018 09:10:42 -0700 Subject: [PATCH] [ember] @ember/array as source of types, ember as re-export --- types/ember/index.d.ts | 438 +----------------- types/ember/tsconfig.json | 2 + types/ember__array/-private/enumerable.d.ts | 173 +++++++ .../-private/mutable-enumerable.d.ts | 28 ++ types/ember__array/-private/native-array.d.ts | 28 ++ types/ember__array/index.d.ts | 106 ++++- types/ember__array/mutable.d.ts | 76 ++- types/ember__array/proxy.d.ts | 22 +- types/ember__array/test/array-ext.ts | 2 +- types/ember__array/test/array.ts | 2 +- types/ember__array/tsconfig.json | 3 + .../types/prototype-extensions.d.ts | 6 +- types/ember__object/-private/copyable.d.ts | 20 + types/ember__object/tsconfig.json | 1 + types/ember__routing/tsconfig.json | 2 + 15 files changed, 477 insertions(+), 432 deletions(-) create mode 100644 types/ember__array/-private/enumerable.d.ts create mode 100644 types/ember__array/-private/mutable-enumerable.d.ts create mode 100644 types/ember__array/-private/native-array.d.ts create mode 100644 types/ember__object/-private/copyable.d.ts diff --git a/types/ember/index.d.ts b/types/ember/index.d.ts index 28965ab872..644fe647ec 100755 --- a/types/ember/index.d.ts +++ b/types/ember/index.d.ts @@ -18,7 +18,7 @@ /// /// /// -/// +/// declare module 'ember' { import { @@ -52,9 +52,14 @@ declare module 'ember' { // tslint:disable-next-line:no-duplicate-imports import EmberMixin from '@ember/object/mixin'; import Observable from '@ember/object/observable'; + // @ember/array + import * as EmberArrayNs from '@ember/array'; + import EmberMutableArray from '@ember/array/mutable'; + import EmberArrayProxy from '@ember/array/proxy'; + import EmberEnumerable from '@ember/array/-private/enumerable'; + import EmberArrayProtoExtensions from '@ember/array/types/prototype-extensions'; - // Get an alias to the global Array type to use in inner scope below. - type GlobalArray = T[]; + type EmberArray = EmberArrayNs.default; type Mix = B & Pick>; type Mix3 = Mix, C>; @@ -253,6 +258,13 @@ declare module 'ember' { } export namespace Ember { + const A: typeof EmberArrayNs.A; + const isArray: typeof EmberArrayNs.isArray; + export type Enumerable = EmberEnumerable; + export const Enumerable: typeof EmberEnumerable; + class ArrayProxy extends EmberArrayProxy {} + export type Array = EmberArray; + export const Array: typeof EmberArrayNs.default; interface FunctionPrototypeExtensions { /** * The `property` extension of Javascript's Function prototype is available @@ -274,7 +286,7 @@ declare module 'ember' { on(...args: string[]): this; } - interface ArrayPrototypeExtensions extends MutableArray, Observable, Copyable {} + interface ArrayPrototypeExtensions extends EmberArrayProtoExtensions {} interface StringPrototypeExtensions { camelize(): string; @@ -484,101 +496,7 @@ declare module 'ember' { running `Application`. **/ class ApplicationInstance extends EngineInstance {} - /** - This module implements Observer-friendly Array-like behavior. This mixin is picked up by the - Array class as well as other controllers, etc. that want to appear to be arrays. - **/ - interface Array extends Enumerable { - /** - * __Required.__ You must implement this method to apply this mixin. - */ - length: number | ComputedProperty; - /** - * Returns the object at the given `index`. If the given `index` is negative - * or is greater or equal than the array length, returns `undefined`. - */ - objectAt(idx: number): T | undefined; - /** - * This returns the objects at the specified indexes, using `objectAt`. - */ - objectsAt(indexes: number[]): Ember.Array; - /** - * Returns a new array that is a slice of the receiver. This implementation - * uses the observable array methods to retrieve the objects for the new - * slice. - */ - slice(beginIndex?: number, endIndex?: number): T[]; - /** - * Returns the index of the given object's first occurrence. - * If no `startAt` argument is given, the starting location to - * search is 0. If it's negative, will count backward from - * the end of the array. Returns -1 if no match is found. - */ - indexOf(searchElement: T, fromIndex?: number): number; - /** - * Returns the index of the given object's last occurrence. - * If no `startAt` argument is given, the search starts from - * the last position. If it's negative, will count backward - * from the end of the array. Returns -1 if no match is found. - */ - lastIndexOf(searchElement: T, fromIndex?: number): number; - /** - * Adds an array observer to the receiving array. The array observer object - * normally must implement two methods: - */ - addArrayObserver(target: {}, opts: {}): this; - /** - * Removes an array observer from the object if the observer is current - * registered. Calling this method multiple times with the same object will - * have no effect. - */ - removeArrayObserver(target: {}, opts: {}): this; - /** - * Becomes true whenever the array currently has observers watching changes - * on the array. - */ - hasArrayObservers: ComputedProperty; - /** - * If you are implementing an object that supports `Ember.Array`, call this - * method just before the array content changes to notify any observers and - * invalidate any related properties. Pass the starting index of the change - * as well as a delta of the amounts to change. - */ - arrayContentWillChange(startIdx: number, removeAmt: number, addAmt: number): this; - /** - * If you are implementing an object that supports `Ember.Array`, call this - * method just after the array content changes to notify any observers and - * invalidate any related properties. Pass the starting index of the change - * as well as a delta of the amounts to change. - */ - arrayContentDidChange(startIdx: number, removeAmt: number, addAmt: number): this; - /** - * Returns a special object that can be used to observe individual properties - * on the array. Just get an equivalent property on this object and it will - * return an enumerable that maps automatically to the named key on the - * member objects. - */ - '@each': ComputedProperty; - } - // Ember.Array rather than Array because the `array-type` lint rule doesn't realize the global is shadowed - const Array: EmberMixin>; - /** - An ArrayProxy wraps any other object that implements Ember.Array and/or Ember.MutableArray, - forwarding all requests. This makes it very useful for a number of binding use cases or other cases - where being able to swap out the underlying array is useful. - **/ - interface ArrayProxy extends MutableArray {} - class ArrayProxy extends Object.extend(MutableArray as {}) { - content: NativeArray; - - /** - * Should actually retrieve the object at the specified index from the - * content. You can override this method in subclasses to transform the - * content item to something new. - */ - objectAtContent(idx: number): T | undefined; - } /** AutoLocation will select the best location option based off browser support with the priority order: history, hash, none. **/ @@ -713,7 +631,7 @@ declare module 'ember' { replaceRoute(name: string, ...args: any[]): void; transitionToRoute(name: string, ...args: any[]): void; model: any; - queryParams: string | string[] | Array<{ [key: string]: { + queryParams: string | string[] | EmberArray<{ [key: string]: { type?: QueryParamTypes, scope?: QueryParamScopeTypes, as?: string @@ -722,23 +640,6 @@ declare module 'ember' { } const ControllerMixin: EmberMixin; class Controller extends Object.extend(ControllerMixin) {} - /** - * Implements some standard methods for copying an object. Add this mixin to - * any object you create that can create a copy of itself. This mixin is - * added automatically to the built-in array. - */ - interface Copyable { - /** - * __Required.__ You must implement this method to apply this mixin. - */ - copy(deep: boolean): Copyable; - /** - * If the object implements `Ember.Freezable`, then this will return a new - * copy if the object is not frozen and the receiver if the object is frozen. - */ - frozenCopy(): Copyable; - } - const Copyable: EmberMixin; // TODO: replace with a proper ES6 reexport once we remove declare module 'ember' {} class Object extends EmberObjectNs.default {} class CoreObject extends EmberCoreObject {} @@ -889,167 +790,7 @@ declare module 'ember' { */ boot(): Promise; } - /** - * This mixin defines the common interface implemented by enumerable objects - * in Ember. Most of these methods follow the standard Array iteration - * API defined up to JavaScript 1.8 (excluding language-specific features that - * cannot be emulated in older versions of JavaScript). - */ - interface Enumerable { - /** - * Helper method returns the first object from a collection. This is usually - * used by bindings and other parts of the framework to extract a single - * object if the enumerable contains only one item. - */ - firstObject: ComputedProperty; - /** - * Helper method returns the last object from a collection. If your enumerable - * contains only one object, this method should always return that object. - * If your enumerable is empty, this method should return `undefined`. - */ - lastObject: ComputedProperty; - /** - * @deprecated Use `Enumerable#includes` instead. - */ - contains(obj: T): boolean; - /** - * Iterates through the enumerable, calling the passed function on each - * item. This method corresponds to the `forEach()` method defined in - * JavaScript 1.6. - */ - forEach: GlobalArray['forEach']; - /** - * Alias for `mapBy` - */ - getEach(key: string): any[]; - /** - * Sets the value on the named property for each member. This is more - * ergonomic than using other methods defined on this helper. If the object - * implements Ember.Observable, the value will be changed to `set(),` otherwise - * it will be set directly. `null` objects are skipped. - */ - setEach(key: string, value: any): any; - /** - * Maps all of the items in the enumeration to another value, returning - * a new array. This method corresponds to `map()` defined in JavaScript 1.6. - */ - map: GlobalArray['map']; - /** - * Similar to map, this specialized function returns the value of the named - * property on all items in the enumeration. - */ - mapBy(key: string): any[]; - /** - * Returns an array with all of the items in the enumeration that the passed - * function returns true for. This method corresponds to `filter()` defined in - * JavaScript 1.6. - */ - filter: GlobalArray['filter']; - /** - * Returns an array with all of the items in the enumeration where the passed - * function returns false. This method is the inverse of filter(). - */ - reject(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): NativeArray; - /** - * Returns an array with just the items with the matched property. You - * can pass an optional second argument with the target value. Otherwise - * this will match any property that evaluates to `true`. - */ - filterBy(key: string, value?: any): NativeArray; - /** - * Returns an array with the items that do not have truthy values for - * key. You can pass an optional second argument with the target value. Otherwise - * this will match any property that evaluates to false. - */ - rejectBy(key: string, value?: any): NativeArray; - /** - * Returns the first item in the array for which the callback returns true. - * This method works similar to the `filter()` method defined in JavaScript 1.6 - * except that it will stop working on the array once a match is found. - */ - find: GlobalArray['find']; - /** - * Returns the first item with a property matching the passed value. You - * can pass an optional second argument with the target value. Otherwise - * this will match any property that evaluates to `true`. - */ - findBy(key: string, value?: any): T | undefined; - /** - * Returns `true` if the passed function returns true for every item in the - * enumeration. This corresponds with the `every()` method in JavaScript 1.6. - */ - every: GlobalArray['every']; - /** - * Returns `true` if the passed property resolves to the value of the second - * argument for all items in the enumerable. This method is often simpler/faster - * than using a callback. - */ - isEvery(key: string, value?: any): boolean; - /** - * Returns `true` if the passed function returns true for any item in the - * enumeration. - */ - any(callback: (value: T, index: number, array: T[]) => boolean, target?: {}): boolean; - /** - * Returns `true` if the passed property resolves to the value of the second - * argument for any item in the enumerable. This method is often simpler/faster - * than using a callback. - */ - isAny(key: string, value?: any): boolean; - /** - * This will combine the values of the enumerator into a single value. It - * is a useful way to collect a summary value from an enumeration. This - * corresponds to the `reduce()` method defined in JavaScript 1.8. - */ - reduce: GlobalArray['reduce']; - /** - * Invokes the named method on every object in the receiver that - * implements it. This method corresponds to the implementation in - * Prototype 1.6. - */ - invoke(methodName: keyof T, ...args: any[]): any[]; - /** - * Simply converts the enumerable into a genuine array. The order is not - * guaranteed. Corresponds to the method implemented by Prototype. - */ - toArray(): T[]; - /** - * Returns a copy of the array with all `null` and `undefined` elements removed. - */ - compact(): NativeArray; - /** - * Returns a new enumerable that excludes the passed value. The default - * implementation returns an array regardless of the receiver type. - * If the receiver does not contain the value it returns the original enumerable. - */ - without(value: T): NativeArray; - /** - * Returns a new enumerable that contains only unique values. The default - * implementation returns an array regardless of the receiver type. - */ - uniq(): NativeArray; - /** - * Converts the enumerable into an array and sorts by the keys - * specified in the argument. - */ - sortBy(property: string): NativeArray; - /** - * Returns a new enumerable that contains only items containing a unique property value. - * The default implementation returns an array regardless of the receiver type. - */ - uniqBy(property: string): NativeArray; - /** - * Returns `true` if the passed object can be found in the enumerable. - */ - includes(searchElement: T, fromIndex?: number): boolean; - /** - * This is the handler for the special array content property. If you get - * this property, it will return this. If you set this property to a new - * array, it will replace the current content. - */ - '[]': ComputedProperty; - } - const Enumerable: EmberMixin>; + /** A subclass of the JavaScript Error object for use in Ember. **/ @@ -1225,118 +966,15 @@ declare module 'ember' { static create(): MapWithDefault; } class Mixin extends EmberMixin {} - /** - * This mixin defines the API for modifying array-like objects. These methods - * can be applied only to a collection that keeps its items in an ordered set. - * It builds upon the Array mixin and adds methods to modify the array. - * One concrete implementations of this class include ArrayProxy. - */ - interface MutableArray extends Array, MutableEnumerable { - /** - * __Required.__ You must implement this method to apply this mixin. - */ - replace(idx: number, amt: number, objects: any[]): any; - /** - * Remove all elements from the array. This is useful if you - * want to reuse an existing array without having to recreate it. - */ - clear(): this; - /** - * This will use the primitive `replace()` method to insert an object at the - * specified index. - */ - insertAt(idx: number, object: {}): this; - /** - * Remove an object at the specified index using the `replace()` primitive - * method. You can pass either a single index, or a start and a length. - */ - removeAt(start: number, len?: number): this; - /** - * Push the object onto the end of the array. Works just like `push()` but it - * is KVO-compliant. - */ - pushObject(obj: T): T; - /** - * Add the objects in the passed numerable to the end of the array. Defers - * notifying observers of the change until all objects are added. - */ - pushObjects(objects: Enumerable): this; - /** - * Pop object from array or nil if none are left. Works just like `pop()` but - * it is KVO-compliant. - */ - popObject(): T; - /** - * Shift an object from start of array or nil if none are left. Works just - * like `shift()` but it is KVO-compliant. - */ - shiftObject(): T; - /** - * Unshift an object to start of array. Works just like `unshift()` but it is - * KVO-compliant. - */ - unshiftObject(obj: T): T; - /** - * Adds the named objects to the beginning of the array. Defers notifying - * observers until all objects have been added. - */ - unshiftObjects(objects: Enumerable): this; - /** - * Reverse objects in the array. Works just like `reverse()` but it is - * KVO-compliant. - */ - reverseObjects(): this; - /** - * Replace all the receiver's content with content of the argument. - * If argument is an empty array receiver will be cleared. - */ - setObjects(objects: Ember.Array): this; - } - const MutableArray: Mixin>; - /** - * This mixin defines the API for modifying generic enumerables. These methods - * can be applied to an object regardless of whether it is ordered or - * unordered. - */ - interface MutableEnumerable extends Enumerable { - /** - * __Required.__ You must implement this method to apply this mixin. - */ - addObject(object: T): T; - /** - * Adds each object in the passed enumerable to the receiver. - */ - addObjects(objects: Enumerable): this; - /** - * __Required.__ You must implement this method to apply this mixin. - */ - removeObject(object: T): T; - /** - * Removes each object in the passed enumerable from the receiver. - */ - removeObjects(objects: Enumerable): this; - } - const MutableEnumerable: Mixin>; + const MutableArray: typeof EmberMutableArray; + /** * A Namespace is an object usually used to contain other objects or methods * such as an application or framework. Create a namespace anytime you want * to define one of these new containers. */ class Namespace extends Object {} - /** - * The NativeArray mixin contains the properties needed to make the native - * Array support Ember.MutableArray and all of its dependent APIs. Unless you - * have `EmberENV.EXTEND_PROTOTYPES` or `EmberENV.EXTEND_PROTOTYPES.Array` set to - * false, this will be applied automatically. Otherwise you can apply the mixin - * at anytime by calling `Ember.NativeArray.apply(Array.prototype)`. - */ - interface NativeArray extends GlobalArray, MutableArray, Observable, Copyable { - /** - * __Required.__ You must implement this method to apply this mixin. - */ - length: number; - } - const NativeArray: Mixin>; + /** * Ember.NoneLocation does not interact with the browser. It is useful for * testing, or when you need to manage state with your Router, but temporarily @@ -2373,15 +2011,6 @@ declare module 'ember' { * loading. Triggers any callbacks registered for this event. */ function runLoadHooks(name: string, object?: {}): any; - /** - * Creates an `Ember.NativeArray` from an Array like object. - * Does not modify the original object's contents. Ember.A is not needed if - * `EmberENV.EXTEND_PROTOTYPES` is `true` (the default value). However, - * it is recommended that you use Ember.A when creating addons for - * ember or when you can not guarantee that `EmberENV.EXTEND_PROTOTYPES` - * will be `true`. - */ - function A(arr?: T[]): NativeArray; const compare: typeof EmberUtilsNs.compare; /** * Creates a shallow copy of the passed object. A deep copy of the object is @@ -2389,10 +2018,6 @@ declare module 'ember' { */ const copy: typeof EmberObjectInternalsNs.copy; const isEqual: typeof EmberUtilsNs.isEqual; - /** - * Returns true if the passed object is an array or Array-like. - */ - function isArray(obj: any): obj is ArrayLike; const typeOf: typeof EmberUtilsNs.typeOf; // TODO: replace with an es6 reexport when declare module 'ember' is removed /** @@ -2621,27 +2246,6 @@ declare module '@ember/application/resolver' { export default class Resolver extends Ember.Resolver { } } -declare module '@ember/array' { - import Ember from 'ember'; - type EmberArray = Ember.Array; - const EmberArray: typeof Ember.Array; - export default EmberArray; - export const A: typeof Ember.A; - export const isArray: typeof Ember.isArray; -} - -declare module '@ember/array/mutable' { - import Ember from 'ember'; - type MutableArray = Ember.MutableArray; - const MutableArray: typeof Ember.MutableArray; - export default MutableArray; -} - -declare module '@ember/array/proxy' { - import Ember from 'ember'; - export default class ArrayProxy extends Ember.ArrayProxy { } -} - declare module '@ember/component' { import Ember from 'ember'; export default class Component extends Ember.Component { } diff --git a/types/ember/tsconfig.json b/types/ember/tsconfig.json index fe41f99a05..14c36f2620 100755 --- a/types/ember/tsconfig.json +++ b/types/ember/tsconfig.json @@ -18,6 +18,8 @@ "@ember/string": ["ember__string"], "@ember/utils": ["ember__utils"], "@ember/utils/*": ["ember__utils/*"], + "@ember/array": ["ember__array"], + "@ember/array/*": ["ember__array/*"], "@ember/object": ["ember__object"], "@ember/object/*": ["ember__object/*"], "@ember/polyfills": ["ember__polyfills"] diff --git a/types/ember__array/-private/enumerable.d.ts b/types/ember__array/-private/enumerable.d.ts new file mode 100644 index 0000000000..cec4a76846 --- /dev/null +++ b/types/ember__array/-private/enumerable.d.ts @@ -0,0 +1,173 @@ +import ComputedProperty from "@ember/object/computed"; +import Mixin from "@ember/object/mixin"; +import NativeArray from "@ember/array/-private/native-array"; +import EmberArray from '@ember/array'; +/** + * This mixin defines the common interface implemented by enumerable objects + * in Ember. Most of these methods follow the standard Array iteration + * API defined up to JavaScript 1.8 (excluding language-specific features that + * cannot be emulated in older versions of JavaScript). + */ +interface Enumerable { + /** + * Helper method returns the first object from a collection. This is usually + * used by bindings and other parts of the framework to extract a single + * object if the enumerable contains only one item. + */ + firstObject: ComputedProperty; + /** + * Helper method returns the last object from a collection. If your enumerable + * contains only one object, this method should always return that object. + * If your enumerable is empty, this method should return `undefined`. + */ + lastObject: ComputedProperty; + /** + * @deprecated Use `Enumerable#includes` instead. + */ + contains(obj: T): boolean; + /** + * Iterates through the enumerable, calling the passed function on each + * item. This method corresponds to the `forEach()` method defined in + * JavaScript 1.6. + */ + forEach: T[]['forEach']; + /** + * Alias for `mapBy` + */ + getEach(key: string): any[]; + /** + * Sets the value on the named property for each member. This is more + * ergonomic than using other methods defined on this helper. If the object + * implements Ember.Observable, the value will be changed to `set(),` otherwise + * it will be set directly. `null` objects are skipped. + */ + setEach(key: string, value: any): any; + /** + * Maps all of the items in the enumeration to another value, returning + * a new array. This method corresponds to `map()` defined in JavaScript 1.6. + */ + map: T[]['map']; + /** + * Similar to map, this specialized function returns the value of the named + * property on all items in the enumeration. + */ + mapBy(key: string): any[]; + /** + * Returns an array with all of the items in the enumeration that the passed + * function returns true for. This method corresponds to `filter()` defined in + * JavaScript 1.6. + */ + filter: T[]['filter']; + /** + * Returns an array with all of the items in the enumeration where the passed + * function returns false. This method is the inverse of filter(). + */ + reject( + callbackfn: (value: T, index: number, array: T[]) => any, + thisArg?: any + ): NativeArray; + /** + * Returns an array with just the items with the matched property. You + * can pass an optional second argument with the target value. Otherwise + * this will match any property that evaluates to `true`. + */ + filterBy(key: string, value?: any): NativeArray; + /** + * Returns an array with the items that do not have truthy values for + * key. You can pass an optional second argument with the target value. Otherwise + * this will match any property that evaluates to false. + */ + rejectBy(key: string, value?: any): NativeArray; + /** + * Returns the first item in the array for which the callback returns true. + * This method works similar to the `filter()` method defined in JavaScript 1.6 + * except that it will stop working on the array once a match is found. + */ + find: T[]['find']; + /** + * Returns the first item with a property matching the passed value. You + * can pass an optional second argument with the target value. Otherwise + * this will match any property that evaluates to `true`. + */ + findBy(key: string, value?: any): T | undefined; + /** + * Returns `true` if the passed function returns true for every item in the + * enumeration. This corresponds with the `every()` method in JavaScript 1.6. + */ + every: T[]['every']; + /** + * Returns `true` if the passed property resolves to the value of the second + * argument for all items in the enumerable. This method is often simpler/faster + * than using a callback. + */ + isEvery(key: string, value?: any): boolean; + /** + * Returns `true` if the passed function returns true for any item in the + * enumeration. + */ + any( + callback: (value: T, index: number, array: T[]) => boolean, + target?: {} + ): boolean; + /** + * Returns `true` if the passed property resolves to the value of the second + * argument for any item in the enumerable. This method is often simpler/faster + * than using a callback. + */ + isAny(key: string, value?: any): boolean; + /** + * This will combine the values of the enumerator into a single value. It + * is a useful way to collect a summary value from an enumeration. This + * corresponds to the `reduce()` method defined in JavaScript 1.8. + */ + reduce: T[]['reduce']; + /** + * Invokes the named method on every object in the receiver that + * implements it. This method corresponds to the implementation in + * Prototype 1.6. + */ + invoke(methodName: keyof T, ...args: any[]): any[]; + /** + * Simply converts the enumerable into a genuine array. The order is not + * guaranteed. Corresponds to the method implemented by Prototype. + */ + toArray(): T[]; + /** + * Returns a copy of the array with all `null` and `undefined` elements removed. + */ + compact(): NativeArray; + /** + * Returns a new enumerable that excludes the passed value. The default + * implementation returns an array regardless of the receiver type. + * If the receiver does not contain the value it returns the original enumerable. + */ + without(value: T): NativeArray; + /** + * Returns a new enumerable that contains only unique values. The default + * implementation returns an array regardless of the receiver type. + */ + uniq(): NativeArray; + /** + * Converts the enumerable into an array and sorts by the keys + * specified in the argument. + */ + sortBy(property: string): NativeArray; + /** + * Returns a new enumerable that contains only items containing a unique property value. + * The default implementation returns an array regardless of the receiver type. + */ + uniqBy(property: string): NativeArray; + /** + * Returns `true` if the passed object can be found in the enumerable. + */ + includes(searchElement: T, fromIndex?: number): boolean; + /** + * This is the handler for the special array content property. If you get + * this property, it will return this. If you set this property to a new + * array, it will replace the current content. + */ + '[]': ComputedProperty; +} +declare const Enumerable: Mixin>; + +export default Enumerable; diff --git a/types/ember__array/-private/mutable-enumerable.d.ts b/types/ember__array/-private/mutable-enumerable.d.ts new file mode 100644 index 0000000000..7757d68431 --- /dev/null +++ b/types/ember__array/-private/mutable-enumerable.d.ts @@ -0,0 +1,28 @@ +import Mixin from "@ember/object/mixin"; +import Enumerable from "@ember/array/-private/enumerable"; + +/** + * This mixin defines the API for modifying generic enumerables. These methods + * can be applied to an object regardless of whether it is ordered or + * unordered. + */ +interface MutableEnumerable extends Enumerable { + /** + * __Required.__ You must implement this method to apply this mixin. + */ + addObject(object: T): T; + /** + * Adds each object in the passed enumerable to the receiver. + */ + addObjects(objects: Enumerable): this; + /** + * __Required.__ You must implement this method to apply this mixin. + */ + removeObject(object: T): T; + /** + * Removes each object in the passed enumerable from the receiver. + */ + removeObjects(objects: Enumerable): this; +} +declare const MutableEnumerable: Mixin>; +export default MutableEnumerable; diff --git a/types/ember__array/-private/native-array.d.ts b/types/ember__array/-private/native-array.d.ts new file mode 100644 index 0000000000..efa258650c --- /dev/null +++ b/types/ember__array/-private/native-array.d.ts @@ -0,0 +1,28 @@ +import MutableArray from "@ember/array/mutable"; +import Observable from "@ember/object/observable"; +import Mixin from "@ember/object/mixin"; +import Copyable from "@ember/object/-private/copyable"; + +// Get an alias to the global Array type to use in inner scope below. +type GlobalArray = T[]; + +/** + * The NativeArray mixin contains the properties needed to make the native + * Array support Ember.MutableArray and all of its dependent APIs. Unless you + * have `EmberENV.EXTEND_PROTOTYPES` or `EmberENV.EXTEND_PROTOTYPES.Array` set to + * false, this will be applied automatically. Otherwise you can apply the mixin + * at anytime by calling `Ember.NativeArray.apply(Array.prototype)`. + */ +interface NativeArray + extends GlobalArray, + MutableArray, + Observable, + Copyable { + /** + * __Required.__ You must implement this method to apply this mixin. + */ + length: number; +} +declare const NativeArray: Mixin>; + +export default NativeArray; diff --git a/types/ember__array/index.d.ts b/types/ember__array/index.d.ts index 991f7961f2..0fca48bfe7 100644 --- a/types/ember__array/index.d.ts +++ b/types/ember__array/index.d.ts @@ -4,10 +4,104 @@ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.8 -import Ember from 'ember'; +import ComputedProperty from "@ember/object/computed"; +import Mixin from "@ember/object/mixin"; +import Enumerable from "@ember/array/-private/enumerable"; +import NativeArray from "@ember/array/-private/native-array"; -type EmberArray = Ember.Array; -export const EmberArray: typeof Ember.Array; -export default EmberArray; -export const A: typeof Ember.A; -export const isArray: typeof Ember.isArray; +/** + * This module implements Observer-friendly Array-like behavior. This mixin is picked up by the + * Array class as well as other controllers, etc. that want to appear to be arrays. + */ +interface Array extends Enumerable { + /** + * __Required.__ You must implement this method to apply this mixin. + */ + length: number | ComputedProperty; + /** + * Returns the object at the given `index`. If the given `index` is negative + * or is greater or equal than the array length, returns `undefined`. + */ + objectAt(idx: number): T | undefined; + /** + * This returns the objects at the specified indexes, using `objectAt`. + */ + // tslint:disable-next-line:array-type + objectsAt(indexes: number[]): Array; + /** + * Returns a new array that is a slice of the receiver. This implementation + * uses the observable array methods to retrieve the objects for the new + * slice. + */ + slice(beginIndex?: number, endIndex?: number): T[]; + /** + * Returns the index of the given object's first occurrence. + * If no `startAt` argument is given, the starting location to + * search is 0. If it's negative, will count backward from + * the end of the array. Returns -1 if no match is found. + */ + indexOf(searchElement: T, fromIndex?: number): number; + /** + * Returns the index of the given object's last occurrence. + * If no `startAt` argument is given, the search starts from + * the last position. If it's negative, will count backward + * from the end of the array. Returns -1 if no match is found. + */ + lastIndexOf(searchElement: T, fromIndex?: number): number; + /** + * Adds an array observer to the receiving array. The array observer object + * normally must implement two methods: + */ + addArrayObserver(target: {}, opts: {}): this; + /** + * Removes an array observer from the object if the observer is current + * registered. Calling this method multiple times with the same object will + * have no effect. + */ + removeArrayObserver(target: {}, opts: {}): this; + /** + * Becomes true whenever the array currently has observers watching changes + * on the array. + */ + hasArrayObservers: ComputedProperty; + /** + * If you are implementing an object that supports `Ember.Array`, call this + * method just before the array content changes to notify any observers and + * invalidate any related properties. Pass the starting index of the change + * as well as a delta of the amounts to change. + */ + arrayContentWillChange(startIdx: number, removeAmt: number, addAmt: number): this; + /** + * If you are implementing an object that supports `Ember.Array`, call this + * method just after the array content changes to notify any observers and + * invalidate any related properties. Pass the starting index of the change + * as well as a delta of the amounts to change. + */ + arrayContentDidChange(startIdx: number, removeAmt: number, addAmt: number): this; + /** + * Returns a special object that can be used to observe individual properties + * on the array. Just get an equivalent property on this object and it will + * return an enumerable that maps automatically to the named key on the + * member objects. + */ + '@each': ComputedProperty; +} +// Ember.Array rather than Array because the `array-type` lint rule doesn't realize the global is shadowed +// tslint:disable-next-line:array-type +declare const Array: Mixin>; +export default Array; + +/** + * Creates an `Ember.NativeArray` from an Array like object. + * Does not modify the original object's contents. Ember.A is not needed if + * `EmberENV.EXTEND_PROTOTYPES` is `true` (the default value). However, + * it is recommended that you use Ember.A when creating addons for + * ember or when you can not guarantee that `EmberENV.EXTEND_PROTOTYPES` + * will be `true`. + */ +export function A(arr?: T[]): NativeArray; + +/** + * Returns true if the passed object is an array or Array-like. + */ +export function isArray(obj: any): obj is ArrayLike; diff --git a/types/ember__array/mutable.d.ts b/types/ember__array/mutable.d.ts index a477c92f69..014377adbc 100644 --- a/types/ember__array/mutable.d.ts +++ b/types/ember__array/mutable.d.ts @@ -1,5 +1,75 @@ -import Ember from 'ember'; +import Mixin from "@ember/object/mixin"; +import MutableEnumerable from "@ember/array/-private/mutable-enumerable"; +import EmberArray from '@ember/array'; +import Enumerable from "@ember/array/-private/enumerable"; + +/** + * This mixin defines the API for modifying array-like objects. These methods + * can be applied only to a collection that keeps its items in an ordered set. + * It builds upon the Array mixin and adds methods to modify the array. + * One concrete implementations of this class include ArrayProxy. + */ +interface MutableArray extends EmberArray, MutableEnumerable { + /** + * __Required.__ You must implement this method to apply this mixin. + */ + replace(idx: number, amt: number, objects: any[]): any; + /** + * Remove all elements from the array. This is useful if you + * want to reuse an existing array without having to recreate it. + */ + clear(): this; + /** + * This will use the primitive `replace()` method to insert an object at the + * specified index. + */ + insertAt(idx: number, object: {}): this; + /** + * Remove an object at the specified index using the `replace()` primitive + * method. You can pass either a single index, or a start and a length. + */ + removeAt(start: number, len?: number): this; + /** + * Push the object onto the end of the array. Works just like `push()` but it + * is KVO-compliant. + */ + pushObject(obj: T): T; + /** + * Add the objects in the passed numerable to the end of the array. Defers + * notifying observers of the change until all objects are added. + */ + pushObjects(objects: Enumerable): this; + /** + * Pop object from array or nil if none are left. Works just like `pop()` but + * it is KVO-compliant. + */ + popObject(): T; + /** + * Shift an object from start of array or nil if none are left. Works just + * like `shift()` but it is KVO-compliant. + */ + shiftObject(): T; + /** + * Unshift an object to start of array. Works just like `unshift()` but it is + * KVO-compliant. + */ + unshiftObject(obj: T): T; + /** + * Adds the named objects to the beginning of the array. Defers notifying + * observers until all objects have been added. + */ + unshiftObjects(objects: Enumerable): this; + /** + * Reverse objects in the array. Works just like `reverse()` but it is + * KVO-compliant. + */ + reverseObjects(): this; + /** + * Replace all the receiver's content with content of the argument. + * If argument is an empty array receiver will be cleared. + */ + setObjects(objects: EmberArray): this; +} +declare const MutableArray: Mixin>; -type MutableArray = Ember.MutableArray; -export const MutableArray: typeof Ember.MutableArray; export default MutableArray; diff --git a/types/ember__array/proxy.d.ts b/types/ember__array/proxy.d.ts index ced7b5c14c..7fd99b114b 100644 --- a/types/ember__array/proxy.d.ts +++ b/types/ember__array/proxy.d.ts @@ -1,3 +1,21 @@ -import Ember from 'ember'; +import MutableArray from "@ember/array/mutable"; +import EmberObject from "@ember/object"; +import NativeArray from "@ember/array/-private/native-array"; -export default class ArrayProxy extends Ember.ArrayProxy { } +/** + * An ArrayProxy wraps any other object that implements Ember.Array and/or Ember.MutableArray, + * forwarding all requests. This makes it very useful for a number of binding use cases or other cases + * where being able to swap out the underlying array is useful. + */ +interface ArrayProxy extends MutableArray {} +declare class ArrayProxy extends EmberObject.extend(MutableArray as {}) { + content: NativeArray; + + /** + * Should actually retrieve the object at the specified index from the + * content. You can override this method in subclasses to transform the + * content item to something new. + */ + objectAtContent(idx: number): T | undefined; +} +export default ArrayProxy; diff --git a/types/ember__array/test/array-ext.ts b/types/ember__array/test/array-ext.ts index 72e9098100..2038eb543b 100755 --- a/types/ember__array/test/array-ext.ts +++ b/types/ember__array/test/array-ext.ts @@ -1,6 +1,6 @@ import { assertType } from './lib/assert'; import EmberObject from '@ember/object'; -import { ArrayPrototypeExtensions } from '@ember/array/types/prototype-extensions'; +import ArrayPrototypeExtensions from '@ember/array/types/prototype-extensions'; declare global { interface Array extends ArrayPrototypeExtensions {} diff --git a/types/ember__array/test/array.ts b/types/ember__array/test/array.ts index 5d578e4319..3755d725c4 100755 --- a/types/ember__array/test/array.ts +++ b/types/ember__array/test/array.ts @@ -30,7 +30,7 @@ const persons6: MutableArray = people.filter((person) => person.get('nam assertType(people.get('[]')); assertType(people.get('[]').get('firstObject')); // $ExpectType any -assertType>(people.mapBy('isHappy')); // $ExpectType Array +assertType(people.mapBy('isHappy')); // $ExpectType boolean[] assertType(people.mapBy('name.length')); const last = people.get('lastObject'); // $ExpectType ({ name: string; isHappy: boolean; } & EmberObject & { name: string; isHappy: boolean; }) | undefined diff --git a/types/ember__array/tsconfig.json b/types/ember__array/tsconfig.json index 425d873101..11e1966393 100644 --- a/types/ember__array/tsconfig.json +++ b/types/ember__array/tsconfig.json @@ -28,6 +28,9 @@ "index.d.ts", "mutable.d.ts", "proxy.d.ts", + "-private/native-array.d.ts", + "-private/enumerable.d.ts", + "-private/mutable-enumerable.d.ts", "types/prototype-extensions.d.ts", "test/lib/assert.ts", "test/array.ts", diff --git a/types/ember__array/types/prototype-extensions.d.ts b/types/ember__array/types/prototype-extensions.d.ts index 42340b83c2..17e5389f81 100644 --- a/types/ember__array/types/prototype-extensions.d.ts +++ b/types/ember__array/types/prototype-extensions.d.ts @@ -1,4 +1,6 @@ -import Ember from 'ember'; +// import Ember from 'ember'; import Observable from '@ember/object/observable'; +import MutableArray from '@ember/array/mutable'; +import Copyable from '@ember/object/-private/copyable'; -export interface ArrayPrototypeExtensions extends Ember.MutableArray, Observable, Ember.Copyable {} +export default interface ArrayPrototypeExtensions extends MutableArray, Observable, Copyable {} diff --git a/types/ember__object/-private/copyable.d.ts b/types/ember__object/-private/copyable.d.ts new file mode 100644 index 0000000000..772e4019b3 --- /dev/null +++ b/types/ember__object/-private/copyable.d.ts @@ -0,0 +1,20 @@ +import Mixin from "@ember/object/mixin"; + +/** + * Implements some standard methods for copying an object. Add this mixin to + * any object you create that can create a copy of itself. This mixin is + * added automatically to the built-in array. + */ +interface Copyable { + /** + * __Required.__ You must implement this method to apply this mixin. + */ + copy(deep: boolean): Copyable; + /** + * If the object implements `Ember.Freezable`, then this will return a new + * copy if the object is not frozen and the receiver if the object is frozen. + */ + frozenCopy(): Copyable; +} +declare const Copyable: Mixin; +export default Copyable; diff --git a/types/ember__object/tsconfig.json b/types/ember__object/tsconfig.json index 079b2f1c4d..aa4a5ee9e2 100644 --- a/types/ember__object/tsconfig.json +++ b/types/ember__object/tsconfig.json @@ -35,6 +35,7 @@ "promise-proxy-mixin.d.ts", "proxy.d.ts", "-private/types.d.ts", + "-private/copyable.d.ts", "test/lib/assert.ts", "test/access-modifier.ts", "test/core.ts", diff --git a/types/ember__routing/tsconfig.json b/types/ember__routing/tsconfig.json index d48c533db5..cdb6a2a2fb 100644 --- a/types/ember__routing/tsconfig.json +++ b/types/ember__routing/tsconfig.json @@ -17,6 +17,8 @@ "paths": { "@ember/object": ["ember__object"], "@ember/object/*": ["ember__object/*"], + "@ember/array": ["ember__array"], + "@ember/array/*": ["ember__array/*"], "@ember/routing": ["ember__routing"], "@ember/routing/*": ["ember__routing/*"] },