diff --git a/types/ember/index.d.ts b/types/ember/index.d.ts index d7aaa35b36..d048007d8f 100755 --- a/types/ember/index.d.ts +++ b/types/ember/index.d.ts @@ -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 // bttf diff --git a/types/ember/test/helper.ts b/types/ember/test/helper.ts index 4743841e31..ec4806b18f 100755 --- a/types/ember/test/helper.ts +++ b/types/ember/test/helper.ts @@ -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, + session: Ember.inject.service('session'), onNewUser: Ember.observer('session.currentUser', function(this: Ember.Helper) { this.recompute(); }), diff --git a/types/ember__controller/ember__controller-tests.ts b/types/ember__controller/ember__controller-tests.ts deleted file mode 100644 index 02307f447c..0000000000 --- a/types/ember__controller/ember__controller-tests.ts +++ /dev/null @@ -1,11 +0,0 @@ -import Controller from '@ember/controller'; - -Controller.extend ({ - queryParams: ['category'], - category: null, - isExpanded: false, - - toggleBody() { - this.toggleProperty('isExpanded'); - } -}); diff --git a/types/ember__controller/index.d.ts b/types/ember__controller/index.d.ts index 77522a3b29..5071811a85 100644 --- a/types/ember__controller/index.d.ts +++ b/types/ember__controller/index.d.ts @@ -31,9 +31,11 @@ export interface ControllerMixin extends ActionHandler { export const ControllerMixin: Mixin; // tslint:disable-next-line:no-empty-interface export default class Controller extends EmberObject.extend(ControllerMixin) {} +export function inject(): ComputedProperty & PropertyDecorator; export function inject( name: K -): ComputedProperty; +): ComputedProperty & 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. diff --git a/types/ember__controller/test/main.ts b/types/ember__controller/test/main.ts new file mode 100644 index 0000000000..88722b0909 --- /dev/null +++ b/types/ember__controller/test/main.ts @@ -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"); + } +}); diff --git a/types/ember__controller/test/octane.ts b/types/ember__controller/test/octane.ts new file mode 100644 index 0000000000..9d4c73bf8d --- /dev/null +++ b/types/ember__controller/test/octane.ts @@ -0,0 +1,26 @@ +import Controller, { inject } from "@ember/controller"; + +class FirstController extends Controller { + foo = "bar"; + @inject second: InstanceType; + @inject() otherSecond: InstanceType; + @inject("second") moreSecond: InstanceType; + + first() { + return ""; + } +} +const SecondController = Controller.extend({ + foo: "bar", + + second() { + return ""; + } +}); + +declare module "@ember/controller" { + interface Registry { + first: FirstController; + second: InstanceType; + } +} diff --git a/types/ember__controller/tsconfig.json b/types/ember__controller/tsconfig.json index 865ec007ac..5ca97b037a 100644 --- a/types/ember__controller/tsconfig.json +++ b/types/ember__controller/tsconfig.json @@ -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" ] } diff --git a/types/ember__object/computed.d.ts b/types/ember__object/computed.d.ts index e63ee86294..8053c5a82a 100644 --- a/types/ember__object/computed.d.ts +++ b/types/ember__object/computed.d.ts @@ -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 { 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 & PropertyDecorator; +/** + * A computed property that performs a logical `and` on the + * original values for the provided dependent properties. + */ +export function and( + ...dependentKeys: string[] +): ComputedProperty & PropertyDecorator; +/** + * A computed property that converts the provided dependent property + * into a boolean value. + */ +export function bool( + dependentKey: string +): ComputedProperty & PropertyDecorator; + +/** + * A computed property that returns the array of values + * for the provided dependent properties. + */ +export function collect( + ...dependentKeys: string[] +): ComputedProperty & 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 & 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 & 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 & 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 & 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 & PropertyDecorator; + +/** + * Filters the array by the property and value + */ +export function filterBy( + dependentKey: string, + propertyKey: string, + value?: any +): ComputedProperty & 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 & 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 & 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 & 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 & 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 & PropertyDecorator; + +/** + * Returns an array mapped via the callback + */ +export function map( + dependentKey: string, + callback: (value: any, index: number, array: any[]) => U +): ComputedProperty & PropertyDecorator; + +/** + * Returns an array mapped to the specified key. + */ +export function mapBy( + dependentKey: string, + propertyKey: string +): ComputedProperty & 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 & 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 & 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 & 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 & PropertyDecorator; +/** + * A computed property that returns the inverse boolean value + * of the original value for the dependent property. + */ +export function not( + dependentKey: string +): ComputedProperty & 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 & 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 & PropertyDecorator; +/** + * A computed property which performs a logical `or` on the + * original values for the provided dependent properties. + */ +export function or( + ...dependentKeys: string[] +): ComputedProperty & 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 & 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 & 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 & 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 & PropertyDecorator; +/** + * A computed property that returns the sum of the values + * in the dependent array. + */ +export function sum( + dependentKey: string +): ComputedProperty & 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 & 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 & 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 & PropertyDecorator; diff --git a/types/ember__object/index.d.ts b/types/ember__object/index.d.ts index f287a51a90..fb5a76efd2 100644 --- a/types/ember__object/index.d.ts +++ b/types/ember__object/index.d.ts @@ -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 // 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( + cb: ComputedPropertyCallback +): ComputedProperty; +declare function computed( + k1: string, + cb: ComputedPropertyCallback +): ComputedProperty; +declare function computed( + k1: string, + k2: string, + cb: ComputedPropertyCallback +): ComputedProperty; +declare function computed( + k1: string, + k2: string, + k3: string, + cb: ComputedPropertyCallback +): ComputedProperty; +declare function computed( + k1: string, + k2: string, + k3: string, + k4: string, + cb: ComputedPropertyCallback +): ComputedProperty; +declare function computed( + k1: string, + k2: string, + k3: string, + k4: string, + k5: string, + cb: ComputedPropertyCallback +): ComputedProperty; +declare function computed( + k1: string, + k2: string, + k3: string, + k4: string, + k5: string, + k6: string, + cb: ComputedPropertyCallback +): ComputedProperty; +declare function computed( + k1: string, + k2: string, + k3: string, + k4: string, + k5: string, + k6: string, + k7: string, + ...rest: any[] +): ComputedProperty; -export const computed: { - (cb: ComputedPropertyCallback): ComputedProperty; - (k1: string, cb: ComputedPropertyCallback): ComputedProperty; - ( - k1: string, - k2: string, - cb: ComputedPropertyCallback - ): ComputedProperty; - ( - k1: string, - k2: string, - k3: string, - cb: ComputedPropertyCallback - ): ComputedProperty; - ( - k1: string, - k2: string, - k3: string, - k4: string, - cb: ComputedPropertyCallback - ): ComputedProperty; - ( - k1: string, - k2: string, - k3: string, - k4: string, - k5: string, - cb: ComputedPropertyCallback - ): ComputedProperty; - ( - k1: string, - k2: string, - k3: string, - k4: string, - k5: string, - k6: string, - cb: ComputedPropertyCallback - ): ComputedProperty; - ( - k1: string, - k2: string, - k3: string, - k4: string, - k5: string, - k6: string, - k7: string, - ...rest: any[] - ): ComputedProperty; +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; - /** - * 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; - /** - * 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; - /** - * A computed property that returns the inverse boolean value - * of the original value for the dependent property. - */ - not(dependentKey: string): ComputedProperty; - /** - * A computed property that converts the provided dependent property - * into a boolean value. - */ - bool(dependentKey: string): ComputedProperty; - /** - * 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; - /** - * A computed property that returns true if the provided dependent property - * is equal to the given value. - */ - equal(dependentKey: string, value: any): ComputedProperty; - /** - * A computed property that returns true if the provided dependent property - * is greater than the provided value. - */ - gt(dependentKey: string, value: number): ComputedProperty; - /** - * 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; - /** - * A computed property that returns true if the provided dependent property - * is less than the provided value. - */ - lt(dependentKey: string, value: number): ComputedProperty; - /** - * 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; - /** - * A computed property that performs a logical `and` on the - * original values for the provided dependent properties. - */ - and(...dependentKeys: string[]): ComputedProperty; - /** - * A computed property which performs a logical `or` on the - * original values for the provided dependent properties. - */ - or(...dependentKeys: string[]): ComputedProperty; - /** - * 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; - /** - * 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; - /** - * 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; - /** - * 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; - /** - * 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; - /** - * @deprecated Missing deprecation options: https://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options - */ - deprecatingAlias( - dependentKey: string, - options?: { id?: string; until?: string } - ): ComputedProperty; - /** - * A computed property that returns the sum of the values - * in the dependent array. - */ - sum(dependentKey: string): ComputedProperty; - /** - * 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; - /** - * 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; - /** - * Returns an array mapped via the callback - */ - map( - dependentKey: string, - callback: (value: any, index: number, array: any[]) => U - ): ComputedProperty; - /** - * Returns an array mapped to the specified key. - */ - mapBy(dependentKey: string, propertyKey: string): ComputedProperty; - /** - * Filters the array by the callback. - */ - filter( - dependentKey: string, - callback: (value: any, index: number, array: any[]) => boolean - ): ComputedProperty; - /** - * Filters the array by the property and value - */ - filterBy( - dependentKey: string, - propertyKey: string, - value?: any - ): ComputedProperty; - /** - * A computed property which returns a new array with all the unique - * elements from one or more dependent arrays. - */ - uniq(propertyKey: string): ComputedProperty; - /** - * 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; - /** - * A computed property which returns a new array with all the unique - * elements from one or more dependent arrays. - */ - union(...propertyKeys: string[]): ComputedProperty; - /** - * A computed property which returns a new array with all the elements - * two or more dependent arrays have in common. - */ - intersect(...propertyKeys: string[]): ComputedProperty; - /** - * 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; - /** - * A computed property that returns the array of values - * for the provided dependent properties. - */ - collect(...dependentKeys: string[]): ComputedProperty; - /** - * 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; -}; +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; diff --git a/types/ember__object/test/octane.ts b/types/ember__object/test/octane.ts new file mode 100644 index 0000000000..d475cab777 --- /dev/null +++ b/types/ember__object/test/octane.ts @@ -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; +} diff --git a/types/ember__object/tsconfig.json b/types/ember__object/tsconfig.json index deeb128e7b..5f6af3fbda 100644 --- a/types/ember__object/tsconfig.json +++ b/types/ember__object/tsconfig.json @@ -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" ] diff --git a/types/ember__service/ember__service-tests.ts b/types/ember__service/ember__service-tests.ts deleted file mode 100644 index ee2e39823c..0000000000 --- a/types/ember__service/ember__service-tests.ts +++ /dev/null @@ -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; - 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 diff --git a/types/ember__service/index.d.ts b/types/ember__service/index.d.ts index 45918f4bbb..416d705940 100644 --- a/types/ember__service/index.d.ts +++ b/types/ember__service/index.d.ts @@ -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; -export function inject( - name: K -): ComputedProperty; +export function inject(): PropertyDecorator & ComputedProperty; // @inject() foo, foo: inject() +export function inject(target: object, propertyKey: string | symbol): void; // @inject foo +export function inject(name: K): PropertyDecorator & ComputedProperty; // @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. diff --git a/types/ember__service/test/main.ts b/types/ember__service/test/main.ts new file mode 100644 index 0000000000..862f499b89 --- /dev/null +++ b/types/ember__service/test/main.ts @@ -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; + 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 diff --git a/types/ember__service/test/octane.ts b/types/ember__service/test/octane.ts new file mode 100644 index 0000000000..c6971e98e4 --- /dev/null +++ b/types/ember__service/test/octane.ts @@ -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; + } +} + +class Foo extends EmberObject { + @inject foo: FirstSvc; + @inject("first") baz: FirstSvc; + @inject() bar: FirstSvc; +} diff --git a/types/ember__service/tsconfig.json b/types/ember__service/tsconfig.json index f1cfe16ca1..1df951cc8a 100644 --- a/types/ember__service/tsconfig.json +++ b/types/ember__service/tsconfig.json @@ -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" ] }