Skip to content

Commit

Permalink
[ember] all computed property descriptors are also PropertyDecorators (
Browse files Browse the repository at this point in the history
  • Loading branch information
dfreeman authored and Konch Roman committed Aug 13, 2019
1 parent a37e086 commit fa72e6b
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 44 deletions.
4 changes: 2 additions & 2 deletions types/ember__controller/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ export interface ControllerMixin extends ActionHandler {
export const ControllerMixin: Mixin<ControllerMixin>;
// tslint:disable-next-line:no-empty-interface
export default class Controller extends EmberObject.extend(ControllerMixin) {}
export function inject(): ComputedProperty<Controller> & PropertyDecorator;
export function inject(): ComputedProperty<Controller>;
export function inject<K extends keyof Registry>(
name: K
): ComputedProperty<Registry[K]> & PropertyDecorator;
): ComputedProperty<Registry[K]>;
export function inject(target: object, propertyKey: string | symbol): void;

// A type registry for Ember `Controller`s. Meant to be declaration-merged
Expand Down
21 changes: 19 additions & 2 deletions types/ember__object/-private/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@ export type ExtractPropertyNamesOfType<T, S> = {

export type Fix<T> = { [K in keyof T]: T[K] };

/**
* Used to capture type information about a computed property, both
* the type of its value and (if it differs) the type its setter expects
* to receive.
*
* Note that this is intentionally a `class` and not a `type` or
* `interface` so that we can sneak in private fields that capture
* type info for the computed property without impacting the
* user-visible type.
*/
export class ComputedPropertyMarker<Get, Set = Get> {
// Necessary in order to avoid losing type information
// see: https://github.com/typed-ember/ember-cli-typescript/issues/246#issuecomment-414812013
private ______getType: Get;
private ______setType: Set;
}

/**
* Used to infer the type of ember classes of type `T`.
*
Expand Down Expand Up @@ -56,7 +73,7 @@ export type MixinOrLiteral<T, Base> = Mixin<T, Base> | T;
/**
* Deconstructs computed properties into the types which would be returned by `.get()`.
*/
export type UnwrapComputedPropertyGetter<T> = T extends ComputedProperty<
export type UnwrapComputedPropertyGetter<T> = T extends ComputedPropertyMarker<
infer U,
any
>
Expand All @@ -66,7 +83,7 @@ export type UnwrapComputedPropertyGetters<T> = {
[P in keyof T]: UnwrapComputedPropertyGetter<T[P]>
};

export type UnwrapComputedPropertySetter<T> = T extends ComputedProperty<
export type UnwrapComputedPropertySetter<T> = T extends ComputedPropertyMarker<
any,
infer V
>
Expand Down
77 changes: 40 additions & 37 deletions types/ember__object/computed.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { computed } from "@ember/object";
import { ComputedPropertyMarker } from "./-private/types";

/**
* A computed property transforms an objects function into a property.
Expand All @@ -7,10 +8,6 @@ import { computed } from "@ember/object";
* This will force the cached result to be recomputed if the dependencies are modified.
*/
export default class ComputedProperty<Get, Set = Get> {
// Necessary in order to avoid losing type information
// see: https://github.com/typed-ember/ember-cli-typescript/issues/246#issuecomment-414812013
private ______getType: Get;
private ______setType: Set;
/**
* Call on a computed property to set it into non-cached mode. When in this
* mode the computed property will not automatically cache the return value.
Expand All @@ -36,36 +33,42 @@ export default class ComputedProperty<Get, Set = Get> {
meta(): {};
}

// Computed property definitions also act as property decorators, including those
// returned from "macros" in third-party code. We additionally include a marker
// interface that we use in `UnwrapComputedProperty{G,S}etters`.
export default interface ComputedProperty<Get, Set = Get>
extends PropertyDecorator, ComputedPropertyMarker<Get, Set> {}

/**
* Creates a new property that is an alias for another property
* on an object. Calls to `get` or `set` this property behave as
* though they were called on the original property.
*/
export function alias(
dependentKey: string
): ComputedProperty<any> & PropertyDecorator;
): ComputedProperty<any>;
/**
* A computed property that performs a logical `and` on the
* original values for the provided dependent properties.
*/
export function and(
...dependentKeys: string[]
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;
/**
* A computed property that converts the provided dependent property
* into a boolean value.
*/
export function bool(
dependentKey: string
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;

/**
* A computed property that returns the array of values
* for the provided dependent properties.
*/
export function collect(
...dependentKeys: string[]
): ComputedProperty<any[]> & PropertyDecorator;
): ComputedProperty<any[]>;

/**
* Creates a new property that is an alias for another property
Expand All @@ -76,30 +79,30 @@ export function collect(
export function deprecatingAlias(
dependentKey: string,
options: { id: string; until: string }
): ComputedProperty<any> & PropertyDecorator;
): ComputedProperty<any>;
/**
* @deprecated Missing deprecation options: https://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options
*/
export function deprecatingAlias(
dependentKey: string,
options?: { id?: string; until?: string }
): ComputedProperty<any> & PropertyDecorator;
): ComputedProperty<any>;

/**
* A computed property that returns true if the value of the dependent
* property is null, an empty string, empty array, or empty function.
*/
export function empty(
dependentKey: string
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;
/**
* A computed property that returns true if the provided dependent property
* is equal to the given value.
*/
export function equal(
dependentKey: string,
value: any
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;
/**
* Expands `pattern`, invoking `callback` for each expansion.
*/
Expand All @@ -114,7 +117,7 @@ export function expandProperties(
export function filter(
dependentKey: string,
callback: (value: any, index: number, array: any[]) => boolean
): ComputedProperty<any[]> & PropertyDecorator;
): ComputedProperty<any[]>;

/**
* Filters the array by the property and value
Expand All @@ -123,7 +126,7 @@ export function filterBy(
dependentKey: string,
propertyKey: string,
value?: any
): ComputedProperty<any[]> & PropertyDecorator;
): ComputedProperty<any[]>;

/**
* A computed property that returns true if the provided dependent property
Expand All @@ -132,23 +135,23 @@ export function filterBy(
export function gt(
dependentKey: string,
value: number
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;
/**
* A computed property that returns true if the provided dependent property
* is greater than or equal to the provided value.
*/
export function gte(
dependentKey: string,
value: number
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;

/**
* A computed property which returns a new array with all the elements
* two or more dependent arrays have in common.
*/
export function intersect(
...propertyKeys: string[]
): ComputedProperty<any[]> & PropertyDecorator;
): ComputedProperty<any[]>;

/**
* A computed property that returns true if the provided dependent property
Expand All @@ -157,31 +160,31 @@ export function intersect(
export function lt(
dependentKey: string,
value: number
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;
/**
* A computed property that returns true if the provided dependent property
* is less than or equal to the provided value.
*/
export function lte(
dependentKey: string,
value: number
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;

/**
* Returns an array mapped via the callback
*/
export function map<U>(
dependentKey: string,
callback: (value: any, index: number, array: any[]) => U
): ComputedProperty<U[]> & PropertyDecorator;
): ComputedProperty<U[]>;

/**
* Returns an array mapped to the specified key.
*/
export function mapBy(
dependentKey: string,
propertyKey: string
): ComputedProperty<any[]> & PropertyDecorator;
): ComputedProperty<any[]>;

/**
* A computed property which matches the original value for the
Expand All @@ -191,7 +194,7 @@ export function mapBy(
export function match(
dependentKey: string,
regexp: RegExp
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;

/**
* A computed property that calculates the maximum value in the
Expand All @@ -200,7 +203,7 @@ export function match(
*/
export function max(
dependentKey: string
): ComputedProperty<number> & PropertyDecorator;
): ComputedProperty<number>;

/**
* A computed property that calculates the minimum value in the
Expand All @@ -209,7 +212,7 @@ export function max(
*/
export function min(
dependentKey: string
): ComputedProperty<number> & PropertyDecorator;
): ComputedProperty<number>;

/**
* A computed property that returns true if the value of the dependent
Expand All @@ -218,21 +221,21 @@ export function min(
*/
export function none(
dependentKey: string
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;
/**
* A computed property that returns the inverse boolean value
* of the original value for the dependent property.
*/
export function not(
dependentKey: string
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;
/**
* A computed property that returns true if the value of the dependent
* property is NOT null, an empty string, empty array, or empty function.
*/
export function notEmpty(
dependentKey: string
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;
/**
* Where `computed.alias` aliases `get` and `set`, and allows for bidirectional
* data flow, `computed.oneWay` only provides an aliased `get`. The `set` will
Expand All @@ -242,29 +245,29 @@ export function notEmpty(
*/
export function oneWay(
dependentKey: string
): ComputedProperty<any> & PropertyDecorator;
): ComputedProperty<any>;
/**
* A computed property which performs a logical `or` on the
* original values for the provided dependent properties.
*/
export function or(
...dependentKeys: string[]
): ComputedProperty<boolean> & PropertyDecorator;
): ComputedProperty<boolean>;
/**
* Where `computed.oneWay` provides oneWay bindings, `computed.readOnly` provides
* a readOnly one way binding. Very often when using `computed.oneWay` one does
* not also want changes to propagate back up, as they will replace the value.
*/
export function readOnly(
dependentKey: string
): ComputedProperty<any> & PropertyDecorator;
): ComputedProperty<any>;
/**
* This is a more semantically meaningful alias of `computed.oneWay`,
* whose name is somewhat ambiguous as to which direction the data flows.
*/
export function reads(
dependentKey: string
): ComputedProperty<any> & PropertyDecorator;
): ComputedProperty<any>;

/**
* A computed property which returns a new array with all the
Expand All @@ -274,7 +277,7 @@ export function reads(
export function setDiff(
setAProperty: string,
setBProperty: string
): ComputedProperty<any[]> & PropertyDecorator;
): ComputedProperty<any[]>;

/**
* A computed property which returns a new array with all the
Expand All @@ -284,30 +287,30 @@ export function setDiff(
export function sort(
itemsKey: string,
sortDefinition: string | ((itemA: any, itemB: any) => number)
): ComputedProperty<any[]> & PropertyDecorator;
): ComputedProperty<any[]>;
/**
* A computed property that returns the sum of the values
* in the dependent array.
*/
export function sum(
dependentKey: string
): ComputedProperty<number> & PropertyDecorator;
): ComputedProperty<number>;

/**
* A computed property which returns a new array with all the unique
* elements from one or more dependent arrays.
*/
export function uniq(
propertyKey: string
): ComputedProperty<any[]> & PropertyDecorator;
): ComputedProperty<any[]>;

/**
* A computed property which returns a new array with all the unique
* elements from one or more dependent arrays.
*/
export function union(
...propertyKeys: string[]
): ComputedProperty<any[]> & PropertyDecorator;
): ComputedProperty<any[]>;

/**
* A computed property which returns a new array with all the unique
Expand All @@ -316,4 +319,4 @@ export function union(
export function uniqBy(
dependentKey: string,
propertyKey: string
): ComputedProperty<any[]> & PropertyDecorator;
): ComputedProperty<any[]>;
2 changes: 1 addition & 1 deletion types/ember__object/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import ComputedProperty, * as ComputedNamespace from "@ember/object/computed";
* see the documentation for each of these.
*/
export default class EmberObject extends CoreObject.extend(Observable) {}
declare function computed(...deps: string[]): (target: object, propertyKey: string) => void;
declare function computed(...deps: string[]): MethodDecorator;
declare function computed<T>(
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
Expand Down

0 comments on commit fa72e6b

Please sign in to comment.