[ember] ember-octane decorator types (#33963)

* [@ember/object] types for @action and @computed decorators

* [@ember/service] add support for ember-octane @inject decorator

* [@ember/object] absolute import in tests

* [@ember/controller] controller @inject decorator for ember-octane

* [ember] lint fixes

* [@ember/object] decorators for computed property macros in ember-octane
This commit is contained in:
Mike North
2019-03-18 08:44:39 -07:00
committed by Wesley Wigham
parent 3d3b075589
commit 59c441bc45
16 changed files with 724 additions and 342 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
// Type definitions for Ember.js 3.0
// Type definitions for Ember.js 3.1
// Project: http://emberjs.com/, https://github.com/emberjs/ember
// Definitions by: Jed Mao <https://github.com/jedmao>
// bttf <https://github.com/bttf>
+7 -1
View File
@@ -14,8 +14,14 @@ class SessionService extends Ember.Service {
currentUser: User;
}
declare module '@ember/service' {
interface Registry {
session: SessionService;
}
}
const CurrentUserEmailHelper = Ember.Helper.extend({
session: Ember.inject.service() as Ember.ComputedProperty<SessionService>,
session: Ember.inject.service('session'),
onNewUser: Ember.observer('session.currentUser', function(this: Ember.Helper) {
this.recompute();
}),
@@ -1,11 +0,0 @@
import Controller from '@ember/controller';
Controller.extend ({
queryParams: ['category'],
category: null,
isExpanded: false,
toggleBody() {
this.toggleProperty('isExpanded');
}
});
+3 -1
View File
@@ -31,9 +31,11 @@ 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<K extends keyof Registry>(
name: K
): ComputedProperty<Registry[K]>;
): ComputedProperty<Registry[K]> & PropertyDecorator;
export function inject(target: object, propertyKey: string | symbol): void;
// A type registry for Ember `Controller`s. Meant to be declaration-merged
// so string lookups resolve to the correct type.
+14
View File
@@ -0,0 +1,14 @@
import Controller, { inject } from "@ember/controller";
Controller.extend({
queryParams: ["category"],
category: null,
isExpanded: false,
first: inject(),
second: inject('second'),
toggleBody() {
this.toggleProperty("isExpanded");
}
});
+26
View File
@@ -0,0 +1,26 @@
import Controller, { inject } from "@ember/controller";
class FirstController extends Controller {
foo = "bar";
@inject second: InstanceType<typeof SecondController>;
@inject() otherSecond: InstanceType<typeof SecondController>;
@inject("second") moreSecond: InstanceType<typeof SecondController>;
first() {
return "";
}
}
const SecondController = Controller.extend({
foo: "bar",
second() {
return "";
}
});
declare module "@ember/controller" {
interface Registry {
first: FirstController;
second: InstanceType<typeof SecondController>;
}
}
+3 -1
View File
@@ -10,6 +10,7 @@
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"experimentalDecorators": true,
"baseUrl": "../",
"typeRoots": [
"../"
@@ -25,6 +26,7 @@
},
"files": [
"index.d.ts",
"ember__controller-tests.ts"
"test/main.ts",
"test/octane.ts"
]
}
+275 -33
View File
@@ -1,4 +1,4 @@
import { computed } from '@ember/object';
import { computed } from "@ember/object";
/**
* A computed property transforms an objects function into a property.
@@ -36,13 +36,70 @@ export default class ComputedProperty<Get, Set = Get> {
meta(): {};
}
export const alias: typeof computed.alias;
export const and: typeof computed.and;
export const bool: typeof computed.bool;
export const collect: typeof computed.collect;
export const deprecatingAlias: typeof computed.deprecatingAlias;
export const empty: typeof computed.empty;
export const equal: typeof computed.equal;
/**
* 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;
/**
* 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;
/**
* A computed property that converts the provided dependent property
* into a boolean value.
*/
export function bool(
dependentKey: string
): ComputedProperty<boolean> & PropertyDecorator;
/**
* A computed property that returns the array of values
* for the provided dependent properties.
*/
export function collect(
...dependentKeys: string[]
): ComputedProperty<any[]> & PropertyDecorator;
/**
* 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, but also
* print a deprecation warning.
*/
export function deprecatingAlias(
dependentKey: string,
options: { id: string; until: string }
): ComputedProperty<any> & PropertyDecorator;
/**
* @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;
/**
* 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;
/**
* 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;
/**
* Expands `pattern`, invoking `callback` for each expansion.
*/
@@ -50,28 +107,213 @@ export function expandProperties(
pattern: string,
callback: (expanded: string) => void
): void;
export const filter: typeof computed.filter;
export const filterBy: typeof computed.filterBy;
export const gt: typeof computed.gt;
export const gte: typeof computed.gte;
export const intersect: typeof computed.intersect;
export const lt: typeof computed.lt;
export const lte: typeof computed.lte;
export const map: typeof computed.map;
export const mapBy: typeof computed.mapBy;
export const match: typeof computed.match;
export const max: typeof computed.max;
export const min: typeof computed.min;
export const none: typeof computed.none;
export const not: typeof computed.not;
export const notEmpty: typeof computed.notEmpty;
export const oneWay: typeof computed.oneWay;
export const or: typeof computed.or;
export const readOnly: typeof computed.readOnly;
export const reads: typeof computed.reads;
export const setDiff: typeof computed.setDiff;
export const sort: typeof computed.sort;
export const sum: typeof computed.sum;
export const union: typeof computed.union;
export const uniq: typeof computed.uniq;
export const uniqBy: typeof computed.uniqBy;
/**
* Filters the array by the callback.
*/
export function filter(
dependentKey: string,
callback: (value: any, index: number, array: any[]) => boolean
): ComputedProperty<any[]> & PropertyDecorator;
/**
* Filters the array by the property and value
*/
export function filterBy(
dependentKey: string,
propertyKey: string,
value?: any
): ComputedProperty<any[]> & PropertyDecorator;
/**
* A computed property that returns true if the provided dependent property
* is greater than the provided value.
*/
export function gt(
dependentKey: string,
value: number
): ComputedProperty<boolean> & PropertyDecorator;
/**
* 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;
/**
* 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;
/**
* A computed property that returns true if the provided dependent property
* is less than the provided value.
*/
export function lt(
dependentKey: string,
value: number
): ComputedProperty<boolean> & PropertyDecorator;
/**
* 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;
/**
* Returns an array mapped via the callback
*/
export function map<U>(
dependentKey: string,
callback: (value: any, index: number, array: any[]) => U
): ComputedProperty<U[]> & PropertyDecorator;
/**
* Returns an array mapped to the specified key.
*/
export function mapBy(
dependentKey: string,
propertyKey: string
): ComputedProperty<any[]> & PropertyDecorator;
/**
* A computed property which matches the original value for the
* dependent property against a given RegExp, returning `true`
* if the value matches the RegExp and `false` if it does not.
*/
export function match(
dependentKey: string,
regexp: RegExp
): ComputedProperty<boolean> & PropertyDecorator;
/**
* A computed property that calculates the maximum value in the
* dependent array. This will return `-Infinity` when the dependent
* array is empty.
*/
export function max(
dependentKey: string
): ComputedProperty<number> & PropertyDecorator;
/**
* A computed property that calculates the minimum value in the
* dependent array. This will return `Infinity` when the dependent
* array is empty.
*/
export function min(
dependentKey: string
): ComputedProperty<number> & PropertyDecorator;
/**
* A computed property that returns true if the value of the dependent
* property is null or undefined. This avoids errors from JSLint complaining
* about use of ==, which can be technically confusing.
*/
export function none(
dependentKey: string
): ComputedProperty<boolean> & PropertyDecorator;
/**
* 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;
/**
* 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;
/**
* Where `computed.alias` aliases `get` and `set`, and allows for bidirectional
* data flow, `computed.oneWay` only provides an aliased `get`. The `set` will
* not mutate the upstream property, rather causes the current property to
* become the value set. This causes the downstream property to permanently
* diverge from the upstream property.
*/
export function oneWay(
dependentKey: string
): ComputedProperty<any> & PropertyDecorator;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* A computed property which returns a new array with all the
* properties from the first dependent array that are not in the second
* dependent array.
*/
export function setDiff(
setAProperty: string,
setBProperty: string
): ComputedProperty<any[]> & PropertyDecorator;
/**
* A computed property which returns a new array with all the
* properties from the first dependent array sorted based on a property
* or sort function.
*/
export function sort(
itemsKey: string,
sortDefinition: string | ((itemA: any, itemB: any) => number)
): ComputedProperty<any[]> & PropertyDecorator;
/**
* A computed property that returns the sum of the values
* in the dependent array.
*/
export function sum(
dependentKey: string
): ComputedProperty<number> & PropertyDecorator;
/**
* 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;
/**
* 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;
/**
* A computed property which returns a new array with all the unique
* elements from an array, with uniqueness determined by specific key.
*/
export function uniqBy(
dependentKey: string,
propertyKey: string
): ComputedProperty<any[]> & PropertyDecorator;
+98 -251
View File
@@ -1,19 +1,20 @@
// Type definitions for non-npm package @ember/object 3.0
// Type definitions for non-npm package @ember/object 3.1
// Project: https://emberjs.com/api/ember/3.4/modules/@ember%2Fobject
// Definitions by: Mike North <https://github.com/mike-north>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.8
import CoreObject from '@ember/object/core';
import Observable from '@ember/object/observable';
import CoreObject from "@ember/object/core";
import Observable from "@ember/object/observable";
import {
ComputedPropertyCallback,
UnwrapComputedPropertyGetter,
UnwrapComputedPropertySetter,
UnwrapComputedPropertyGetters,
UnwrapComputedPropertySetters
} from '@ember/object/-private/types';
import ComputedProperty from '@ember/object/computed';
UnwrapComputedPropertySetters,
ExtractPropertyNamesOfType
} from "@ember/object/-private/types";
import ComputedProperty, * as ComputedNamespace from "@ember/object/computed";
/**
* `Ember.Object` is the main base class for all Ember objects. It is a subclass
@@ -21,252 +22,96 @@ import ComputedProperty 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<T>(
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
declare function computed<T>(
k1: string,
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
declare function computed<T>(
k1: string,
k2: string,
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
declare function computed<T>(
k1: string,
k2: string,
k3: string,
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
declare function computed<T>(
k1: string,
k2: string,
k3: string,
k4: string,
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
declare function computed<T>(
k1: string,
k2: string,
k3: string,
k4: string,
k5: string,
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
declare function computed<T>(
k1: string,
k2: string,
k3: string,
k4: string,
k5: string,
k6: string,
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
declare function computed(
k1: string,
k2: string,
k3: string,
k4: string,
k5: string,
k6: string,
k7: string,
...rest: any[]
): ComputedProperty<any>;
export const computed: {
<T>(cb: ComputedPropertyCallback<T>): ComputedProperty<T>;
<T>(k1: string, cb: ComputedPropertyCallback<T>): ComputedProperty<T>;
<T>(
k1: string,
k2: string,
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
<T>(
k1: string,
k2: string,
k3: string,
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
<T>(
k1: string,
k2: string,
k3: string,
k4: string,
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
<T>(
k1: string,
k2: string,
k3: string,
k4: string,
k5: string,
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
<T>(
k1: string,
k2: string,
k3: string,
k4: string,
k5: string,
k6: string,
cb: ComputedPropertyCallback<T>
): ComputedProperty<T>;
(
k1: string,
k2: string,
k3: string,
k4: string,
k5: string,
k6: string,
k7: string,
...rest: any[]
): ComputedProperty<any>;
declare namespace computed {
const empty: typeof ComputedNamespace.empty;
const notEmpty: typeof ComputedNamespace.notEmpty;
const none: typeof ComputedNamespace.none;
const not: typeof ComputedNamespace.not;
const bool: typeof ComputedNamespace.bool;
const match: typeof ComputedNamespace.match;
const equal: typeof ComputedNamespace.equal;
const gt: typeof ComputedNamespace.gt;
const gte: typeof ComputedNamespace.gte;
const lt: typeof ComputedNamespace.lt;
const lte: typeof ComputedNamespace.lte;
const and: typeof ComputedNamespace.and;
const or: typeof ComputedNamespace.or;
const alias: typeof ComputedNamespace.alias;
const oneWay: typeof ComputedNamespace.oneWay;
const reads: typeof ComputedNamespace.reads;
const readOnly: typeof ComputedNamespace.readOnly;
const deprecatingAlias: typeof ComputedNamespace.deprecatingAlias;
const sum: typeof ComputedNamespace.sum;
const max: typeof ComputedNamespace.max;
const min: typeof ComputedNamespace.min;
const map: typeof ComputedNamespace.map;
const mapBy: typeof ComputedNamespace.mapBy;
const filter: typeof ComputedNamespace.filter;
const filterBy: typeof ComputedNamespace.filterBy;
const uniq: typeof ComputedNamespace.uniq;
const uniqBy: typeof ComputedNamespace.uniqBy;
const union: typeof ComputedNamespace.union;
const intersect: typeof ComputedNamespace.intersect;
const setDiff: typeof ComputedNamespace.setDiff;
const collect: typeof ComputedNamespace.collect;
const sort: typeof ComputedNamespace.sort;
}
/**
* A computed property that returns true if the value of the dependent
* property is null, an empty string, empty array, or empty function.
*/
empty(dependentKey: string): 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.
*/
notEmpty(dependentKey: string): ComputedProperty<boolean>;
/**
* A computed property that returns true if the value of the dependent
* property is null or undefined. This avoids errors from JSLint complaining
* about use of ==, which can be technically confusing.
*/
none(dependentKey: string): ComputedProperty<boolean>;
/**
* A computed property that returns the inverse boolean value
* of the original value for the dependent property.
*/
not(dependentKey: string): ComputedProperty<boolean>;
/**
* A computed property that converts the provided dependent property
* into a boolean value.
*/
bool(dependentKey: string): ComputedProperty<boolean>;
/**
* A computed property which matches the original value for the
* dependent property against a given RegExp, returning `true`
* if the value matches the RegExp and `false` if it does not.
*/
match(dependentKey: string, regexp: RegExp): ComputedProperty<boolean>;
/**
* A computed property that returns true if the provided dependent property
* is equal to the given value.
*/
equal(dependentKey: string, value: any): ComputedProperty<boolean>;
/**
* A computed property that returns true if the provided dependent property
* is greater than the provided value.
*/
gt(dependentKey: string, value: number): ComputedProperty<boolean>;
/**
* A computed property that returns true if the provided dependent property
* is greater than or equal to the provided value.
*/
gte(dependentKey: string, value: number): ComputedProperty<boolean>;
/**
* A computed property that returns true if the provided dependent property
* is less than the provided value.
*/
lt(dependentKey: string, value: number): ComputedProperty<boolean>;
/**
* A computed property that returns true if the provided dependent property
* is less than or equal to the provided value.
*/
lte(dependentKey: string, value: number): ComputedProperty<boolean>;
/**
* A computed property that performs a logical `and` on the
* original values for the provided dependent properties.
*/
and(...dependentKeys: string[]): ComputedProperty<boolean>;
/**
* A computed property which performs a logical `or` on the
* original values for the provided dependent properties.
*/
or(...dependentKeys: string[]): ComputedProperty<boolean>;
/**
* 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.
*/
alias(dependentKey: string): ComputedProperty<any>;
/**
* Where `computed.alias` aliases `get` and `set`, and allows for bidirectional
* data flow, `computed.oneWay` only provides an aliased `get`. The `set` will
* not mutate the upstream property, rather causes the current property to
* become the value set. This causes the downstream property to permanently
* diverge from the upstream property.
*/
oneWay(dependentKey: string): ComputedProperty<any>;
/**
* This is a more semantically meaningful alias of `computed.oneWay`,
* whose name is somewhat ambiguous as to which direction the data flows.
*/
reads(dependentKey: string): ComputedProperty<any>;
/**
* 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.
*/
readOnly(dependentKey: string): ComputedProperty<any>;
/**
* 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, but also
* print a deprecation warning.
*/
deprecatingAlias(
dependentKey: string,
options: { id: string; until: string }
): ComputedProperty<any>;
/**
* @deprecated Missing deprecation options: https://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options
*/
deprecatingAlias(
dependentKey: string,
options?: { id?: string; until?: string }
): ComputedProperty<any>;
/**
* A computed property that returns the sum of the values
* in the dependent array.
*/
sum(dependentKey: string): ComputedProperty<number>;
/**
* A computed property that calculates the maximum value in the
* dependent array. This will return `-Infinity` when the dependent
* array is empty.
*/
max(dependentKey: string): ComputedProperty<number>;
/**
* A computed property that calculates the minimum value in the
* dependent array. This will return `Infinity` when the dependent
* array is empty.
*/
min(dependentKey: string): ComputedProperty<number>;
/**
* Returns an array mapped via the callback
*/
map<U>(
dependentKey: string,
callback: (value: any, index: number, array: any[]) => U
): ComputedProperty<U[]>;
/**
* Returns an array mapped to the specified key.
*/
mapBy(dependentKey: string, propertyKey: string): ComputedProperty<any[]>;
/**
* Filters the array by the callback.
*/
filter(
dependentKey: string,
callback: (value: any, index: number, array: any[]) => boolean
): ComputedProperty<any[]>;
/**
* Filters the array by the property and value
*/
filterBy(
dependentKey: string,
propertyKey: string,
value?: any
): ComputedProperty<any[]>;
/**
* A computed property which returns a new array with all the unique
* elements from one or more dependent arrays.
*/
uniq(propertyKey: string): ComputedProperty<any[]>;
/**
* A computed property which returns a new array with all the unique
* elements from an array, with uniqueness determined by specific key.
*/
uniqBy(dependentKey: string, propertyKey: string): ComputedProperty<any[]>;
/**
* A computed property which returns a new array with all the unique
* elements from one or more dependent arrays.
*/
union(...propertyKeys: string[]): ComputedProperty<any[]>;
/**
* A computed property which returns a new array with all the elements
* two or more dependent arrays have in common.
*/
intersect(...propertyKeys: string[]): ComputedProperty<any[]>;
/**
* A computed property which returns a new array with all the
* properties from the first dependent array that are not in the second
* dependent array.
*/
setDiff(
setAProperty: string,
setBProperty: string
): ComputedProperty<any[]>;
/**
* A computed property that returns the array of values
* for the provided dependent properties.
*/
collect(...dependentKeys: string[]): ComputedProperty<any[]>;
/**
* A computed property which returns a new array with all the
* properties from the first dependent array sorted based on a property
* or sort function.
*/
sort(
itemsKey: string,
sortDefinition: string | ((itemA: any, itemB: any) => number)
): ComputedProperty<any[]>;
};
export { computed };
/**
* Specify a method that observes property changes.
*/
@@ -387,7 +232,9 @@ export function defineProperty(
export function notifyPropertyChange(obj: object, keyName: string): void;
declare module '@ember/utils/-private/types' {
export const action: MethodDecorator;
declare module "@ember/utils/-private/types" {
interface TypeLookup {
class: typeof EmberObject;
instance: EmberObject;
+217
View File
@@ -0,0 +1,217 @@
import { action, computed, default as EmberObject } from "@ember/object";
import {
alias,
and,
bool,
collect,
deprecatingAlias,
empty,
equal,
filter,
filterBy,
gt,
gte,
intersect,
lt,
lte,
map,
mapBy,
match,
max,
min,
none,
not,
notEmpty,
oneWay,
or,
readOnly,
reads,
setDiff,
sort,
sum,
union,
uniq,
uniqBy
} from "@ember/object/computed";
// Native class syntax
class Foo extends EmberObject {
firstName: string;
lastName: string;
@action // $ExpectError
bar: string;
@computed("firstName", "lastName")
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
@action
foo() {}
}
// Computed property macros
class Bar extends EmberObject {
firstName: string;
last: string;
values: number[];
@alias aliasTest0: string; // $ExpectError
@alias() aliasTest1: string; // $ExpectError
@alias("firstName") aliasTest2: string;
@and andTest0: boolean; // $ExpectError
@and() andTest1: boolean;
@and("firstName") andTest2: boolean;
@and("firstName", "lastName") andTest3: boolean;
@bool boolTest0: boolean; // $ExpectError
@bool() boolTest1: boolean; // $ExpectError
@bool("firstName") boolTest2: boolean;
@collect collectTest0: any; // $ExpectError
@collect() collectTest1: any;
@collect("firstName") collectTest2: any;
@deprecatingAlias deprecatingAliasTest0: string; // $ExpectError
@deprecatingAlias() deprecatingAliasTest1: string; // $ExpectError
@deprecatingAlias("firstName") deprecatingAliasTest2: string;
@empty emptyTest0: boolean; // $ExpectError
@empty() emptyTest1: boolean; // $ExpectError
@empty("firstName") emptyTest2: boolean;
@equal equalTest0: boolean; // $ExpectError
@equal() equalTest1: boolean; // $ExpectError
@equal("firstName") equalTest2: boolean; // $ExpectError
@equal("firstName", "lastName") equalTest3: boolean;
@filter filterTest1: string[]; // $ExpectError
@filter() filterTest2: string[]; // $ExpectError
@filter("firstName") filterTest3: string[]; // $ExpectError
@filter("firstName", x => x) filterTest4: string[];
@filterBy filterByTest1: any[]; // $ExpectError
@filterBy() filterByTest2: any[]; // $ExpectError
@filterBy("firstName") filterByTest3: any[]; // $ExpectError
@filterBy("firstName", "id") filterByTest4: any[];
@gt gtTest1: boolean; // $ExpectError
@gt() gtTest2: boolean; // $ExpectError
@gt("firstName") gtTest3: boolean; // $ExpectError
@gt("firstName", 3) gtTest4: boolean;
@gte gteTest1: boolean; // $ExpectError
@gte() gteTest2: boolean; // $ExpectError
@gte("firstName") gteTest3: boolean; // $ExpectError
@gte("firstName", 3) gteTest4: boolean;
@intersect intersectTest1: any; // $ExpectError
@intersect() intersectTest2: any;
@intersect("firstName") intersectTest3: any;
@intersect("firstName", "lastName") intersectTest4: any;
@lt ltTest1: boolean; // $ExpectError
@lt() ltTest2: boolean; // $ExpectError
@lt("firstName") ltTest3: boolean; // $ExpectError
@lt("firstName", 3) ltTest4: boolean;
@lte lteTest1: boolean; // $ExpectError
@lte() lteTest2: boolean; // $ExpectError
@lte("firstName") lteTest3: boolean; // $ExpectError
@lte("firstName", 3) lteTest4: boolean;
@map mapTest1: string[]; // $ExpectError
@map() mapTest2: string[]; // $ExpectError
@map("firstName") mapTest3: string[]; // $ExpectError
@map("firstName", x => x) mapTest4: string[];
@mapBy mapByTest1: any[]; // $ExpectError
@mapBy() mapByTest2: any[]; // $ExpectError
@mapBy("firstName") mapByTest3: any[]; // $ExpectError
@mapBy("firstName", "id") mapByTest4: any[];
@match matchTest1: boolean; // $ExpectError
@match() matchTest2: boolean; // $ExpectError
@match("firstName") matchTest3: boolean; // $ExpectError
@match("firstName", "abc") matchTest4: boolean; // $ExpectError
@match("firstName", /\s+/) matchTest5: boolean;
@max maxTest1: number; // $ExpectError
@max() maxTest2: number; // $ExpectError
@max("values") maxTest3: number;
@max("values", "a") maxTest4: number; // $ExpectError
@min minTest1: number; // $ExpectError
@min() minTest2: number; // $ExpectError
@min("values") minTest3: number;
@min("values", "a") minTest4: number; // $ExpectError
@none noneTest1: number; // $ExpectError
@none() noneTest2: number; // $ExpectError
@none("values") noneTest3: number;
@none("values", "a") noneTest4: number; // $ExpectError
@not notTest1: number; // $ExpectError
@not() notTest2: number; // $ExpectError
@not("values") notTest3: number;
@not("values", "a") notTest4: number; // $ExpectError
@notEmpty notEmptyTest1: boolean; // $ExpectError
@notEmpty() notEmptyTest2: boolean; // $ExpectError
@notEmpty("firstName") notEmptyTest3: boolean;
@notEmpty("firstName", "a") notEmptyTest4: boolean; // $ExpectError
@oneWay oneWayTest1: boolean; // $ExpectError
@oneWay() oneWayTest2: boolean; // $ExpectError
@oneWay("firstName") oneWayTest3: boolean;
@oneWay("firstName", "b") oneWayTest4: boolean; // $ExpectError
@or orTest1: boolean; // $ExpectError
@or() orTest2: boolean;
@or("firstName") orTest3: boolean;
@or("firstName", "lastName") orTest4: boolean;
@readOnly readOnlyTest1: boolean; // $ExpectError
@readOnly() readOnlyTest2: boolean; // $ExpectError
@readOnly("firstName") readOnlyTest3: boolean;
@reads readsTest1: boolean; // $ExpectError
@reads() readsTest2: boolean; // $ExpectError
@reads("firstName") readsTest3: boolean;
@reads("firstName", "a") readsTest4: boolean; // $ExpectError
@setDiff setDiffTest1: number; // $ExpectError
@setDiff() setDiffTest2: number; // $ExpectError
@setDiff("values") setDiffTest3: number; // $ExpectError
@setDiff("values", "otherThing") setDiffTest4: number;
@setDiff("values", "otherThing", "a") setDiffTest5: number; // $ExpectError
@sort sortTest1: number; // $ExpectError
@sort() sortTest2: number; // $ExpectError
@sort("values") sortTest3: number; // $ExpectError
@sort("values", "id") sortTest4: number;
@sort("values", "id", "a") sortTest5: number; // $ExpectError
@sort("values", (a, b) => a - b) sortTest6: number;
@sum sumTest1: number; // $ExpectError
@sum() sumTest2: number; // $ExpectError
@sum("values") sumTest3: number;
@union unionTest1: any; // $ExpectError
@union() unionTest2: any;
@union("firstName") unionTest3: any;
@union("firstName", "lastName") unionTest4: any;
@uniq uniqTest1: number; // $ExpectError
@uniq() uniqTest2: number; // $ExpectError
@uniq("values") uniqTest3: number;
@uniqBy uniqByTest1: number; // $ExpectError
@uniqBy() uniqByTest2: number; // $ExpectError
@uniqBy("values") uniqByTest3: number; // $ExpectError
@uniqBy("values", "id") uniqByTest4: number;
}
+2
View File
@@ -11,6 +11,7 @@
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": "../",
"experimentalDecorators": true,
"typeRoots": [
"../"
],
@@ -49,6 +50,7 @@
"test/extend.ts",
"test/object.ts",
"test/observable.ts",
"test/octane.ts",
"test/proxy.ts",
"test/reopen.ts"
]
@@ -1,38 +0,0 @@
import Service, { inject } from "@ember/service";
import EmberObject from "@ember/object";
class FirstSvc extends Service {
foo = 'bar';
first() { return ''; }
}
const SecondSvc = Service.extend({
foo: 'bar',
second() { return ''; }
});
class ThirdSvc extends Service.extend({
foo: 'bar',
third() { return ''; }
}) { }
declare module '@ember/service' {
interface Registry {
first: FirstSvc;
second: InstanceType<typeof SecondSvc>;
third: ThirdSvc;
}
}
const ServiceTriplet = EmberObject.extend({
sFirst: inject('first'),
sSecond: inject('second'),
sThird: inject('third'),
unknownService: inject()
});
const obj = ServiceTriplet.create();
obj.get('sFirst'); // $ExpectType FirstSvc
obj.get('sSecond').second(); // $ExpectType ""
obj.get('sThird'); // $ExpectType ThirdSvc
obj.get('unknownService'); // $ExpectType Service
+3 -4
View File
@@ -12,10 +12,9 @@ export default class Service extends EmberObject {}
* Creates a property that lazily looks up a service in the container. There
* are no restrictions as to what objects a service can be injected into.
*/
export function inject(): ComputedProperty<Service>;
export function inject<K extends keyof Registry>(
name: K
): ComputedProperty<Registry[K]>;
export function inject(): PropertyDecorator & ComputedProperty<Service>; // @inject() foo, foo: inject()
export function inject(target: object, propertyKey: string | symbol): void; // @inject foo
export function inject<K extends keyof Registry>(name: K): PropertyDecorator & ComputedProperty<Registry[K]>; // @inject('store') foo @inject() foo
// A type registry for Ember `Service`s. Meant to be declaration-merged so
// string lookups resolve to the correct type.
+44
View File
@@ -0,0 +1,44 @@
import Service, { inject } from "@ember/service";
import EmberObject from "@ember/object";
class FirstSvc extends Service {
foo = "bar";
first() {
return "";
}
}
const SecondSvc = Service.extend({
foo: "bar",
second() {
return "";
}
});
class ThirdSvc extends Service.extend({
foo: "bar",
third() {
return "";
}
}) {}
declare module "@ember/service" {
interface Registry {
first: FirstSvc;
second: InstanceType<typeof SecondSvc>;
third: ThirdSvc;
}
}
const ServiceTriplet = EmberObject.extend({
sFirst: inject("first"),
sSecond: inject("second"),
sThird: inject("third"),
unknownService: inject()
});
const obj = ServiceTriplet.create();
obj.get("sFirst"); // $ExpectType FirstSvc
obj.get("sSecond").second(); // $ExpectType ""
obj.get("sThird"); // $ExpectType ThirdSvc
obj.get("unknownService"); // $ExpectType Service
+28
View File
@@ -0,0 +1,28 @@
import Service, { inject } from "@ember/service";
import EmberObject from "@ember/object";
class FirstSvc extends Service {
foo = "bar";
first() {
return "";
}
}
const SecondSvc = Service.extend({
foo: "bar",
second() {
return "";
}
});
declare module "@ember/service" {
interface Registry {
first: FirstSvc;
second: InstanceType<typeof SecondSvc>;
}
}
class Foo extends EmberObject {
@inject foo: FirstSvc;
@inject("first") baz: FirstSvc;
@inject() bar: FirstSvc;
}
+3 -1
View File
@@ -10,6 +10,7 @@
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"experimentalDecorators": true,
"baseUrl": "../",
"typeRoots": [
"../"
@@ -25,6 +26,7 @@
},
"files": [
"index.d.ts",
"ember__service-tests.ts"
"test/main.ts",
"test/octane.ts"
]
}