From b49e87cd192f2eb2c0369c1ee723f5cb0d0c8222 Mon Sep 17 00:00:00 2001 From: Mike North Date: Fri, 14 Sep 2018 09:45:37 -0700 Subject: [PATCH] [ember] @ember/array types refactored into their own package (#28836) --- types/ember__array/index.d.ts | 13 +++++ types/ember__array/mutable.d.ts | 5 ++ types/ember__array/proxy.d.ts | 3 + types/ember__array/test/array-ext.ts | 22 ++++++++ types/ember__array/test/array-proxy.ts | 27 +++++++++ types/ember__array/test/array.ts | 56 +++++++++++++++++++ types/ember__array/test/lib/assert.ts | 5 ++ types/ember__array/tsconfig.json | 35 ++++++++++++ types/ember__array/tslint.json | 4 ++ .../types/prototype-extensions.d.ts | 3 + 10 files changed, 173 insertions(+) create mode 100644 types/ember__array/index.d.ts create mode 100644 types/ember__array/mutable.d.ts create mode 100644 types/ember__array/proxy.d.ts create mode 100755 types/ember__array/test/array-ext.ts create mode 100644 types/ember__array/test/array-proxy.ts create mode 100755 types/ember__array/test/array.ts create mode 100755 types/ember__array/test/lib/assert.ts create mode 100644 types/ember__array/tsconfig.json create mode 100644 types/ember__array/tslint.json create mode 100644 types/ember__array/types/prototype-extensions.d.ts diff --git a/types/ember__array/index.d.ts b/types/ember__array/index.d.ts new file mode 100644 index 0000000000..991f7961f2 --- /dev/null +++ b/types/ember__array/index.d.ts @@ -0,0 +1,13 @@ +// Type definitions for @ember/array 3.0 +// Project: http://emberjs.com/ +// Definitions by: Mike North +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +import Ember from 'ember'; + +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; diff --git a/types/ember__array/mutable.d.ts b/types/ember__array/mutable.d.ts new file mode 100644 index 0000000000..a477c92f69 --- /dev/null +++ b/types/ember__array/mutable.d.ts @@ -0,0 +1,5 @@ +import Ember from 'ember'; + +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 new file mode 100644 index 0000000000..ced7b5c14c --- /dev/null +++ b/types/ember__array/proxy.d.ts @@ -0,0 +1,3 @@ +import Ember from 'ember'; + +export default class ArrayProxy extends Ember.ArrayProxy { } diff --git a/types/ember__array/test/array-ext.ts b/types/ember__array/test/array-ext.ts new file mode 100755 index 0000000000..72e9098100 --- /dev/null +++ b/types/ember__array/test/array-ext.ts @@ -0,0 +1,22 @@ +import { assertType } from './lib/assert'; +import EmberObject from '@ember/object'; +import { ArrayPrototypeExtensions } from '@ember/array/types/prototype-extensions'; + +declare global { + interface Array extends ArrayPrototypeExtensions {} +} + +class Person extends EmberObject { + name: string; +} + +const person = Person.create({ name: 'Joe' }); +const array = [person]; + +assertType(array.get('length')); +assertType(array.get('firstObject')); +assertType(array.mapBy('name')); +assertType(array.map(p => p.get('name'))); +assertType(array.sortBy('name')); +assertType(array.uniq()); +assertType(array.uniqBy('name')); diff --git a/types/ember__array/test/array-proxy.ts b/types/ember__array/test/array-proxy.ts new file mode 100644 index 0000000000..f4ca116e14 --- /dev/null +++ b/types/ember__array/test/array-proxy.ts @@ -0,0 +1,27 @@ +import { assertType } from './lib/assert'; +import ArrayProxy from '@ember/array/proxy'; +import { A } from '@ember/array'; + +const pets = ['dog', 'cat', 'fish']; +const proxy = ArrayProxy.create({ content: A(pets) }); + +proxy.get('firstObject'); // 'dog' +proxy.set('content', A(['amoeba', 'paramecium'])); +proxy.get('firstObject'); // 'amoeba' + +const overridden = ArrayProxy.create({ + content: A(pets), + objectAtContent(idx: number): string { + return this.get('content').objectAt(idx)!.toUpperCase(); + } +}); + +overridden.get('firstObject'); // 'DOG' + +class MyNewProxy extends ArrayProxy { + isNew = true; +} + +const x = MyNewProxy.create({ content: A([1, 2, 3]) }) as MyNewProxy; +assertType(x.get('firstObject')); +assertType(x.isNew); diff --git a/types/ember__array/test/array.ts b/types/ember__array/test/array.ts new file mode 100755 index 0000000000..5d578e4319 --- /dev/null +++ b/types/ember__array/test/array.ts @@ -0,0 +1,56 @@ +import { assertType } from './lib/assert'; +import EmberObject from '@ember/object'; +import EmberArray, { A } from '@ember/array'; +import MutableArray from '@ember/array/mutable'; + +type Person = typeof Person.prototype; +const Person = EmberObject.extend({ + name: '', + isHappy: false +}); + +const people = A([ + Person.create({ name: 'Yehuda', isHappy: true }), + Person.create({ name: 'Majd', isHappy: false }), +]); + +assertType(people.get('length')); +assertType(people.get('lastObject')); +assertType(people.get('firstObject')); +assertType(people.isAny('isHappy')); +assertType(people.isAny('isHappy', 'false')); + +const persons1: Person[] = people.filterBy('isHappy'); +const persons2: MutableArray = people.filterBy('isHappy'); +const persons3: Person[] = people.rejectBy('isHappy'); +const persons4: MutableArray = people.rejectBy('isHappy'); +const persons5: Person[] = people.filter((person) => person.get('name') === 'Yehuda'); +const persons6: MutableArray = people.filter((person) => person.get('name') === 'Yehuda'); + +assertType(people.get('[]')); +assertType(people.get('[]').get('firstObject')); // $ExpectType any + +assertType>(people.mapBy('isHappy')); // $ExpectType Array +assertType(people.mapBy('name.length')); + +const last = people.get('lastObject'); // $ExpectType ({ name: string; isHappy: boolean; } & EmberObject & { name: string; isHappy: boolean; }) | undefined +if (last) { + assertType(last.get('name')); +} + +const first = people.get('lastObject'); +if (first) { + assertType(first.get('isHappy')); +} + +const letters: EmberArray = A(['a', 'b', 'c']); +const codes: number[] = letters.map((item, index, enumerable) => { + assertType(item); + assertType(index); + return item.charCodeAt(0); +}); + +const value = '1,2,3'; +const filters = A(value.split(',')); +filters.push('4'); +filters.sort(); diff --git a/types/ember__array/test/lib/assert.ts b/types/ember__array/test/lib/assert.ts new file mode 100755 index 0000000000..262d18bc2c --- /dev/null +++ b/types/ember__array/test/lib/assert.ts @@ -0,0 +1,5 @@ +/** Static assertion that `value` has type `T` */ +// Disable tslint here b/c the generic is used to let us do a type coercion and +// validate that coercion works for the type value "passed into" the function. +// tslint:disable-next-line:no-unnecessary-generics +export declare function assertType(value: T): T; diff --git a/types/ember__array/tsconfig.json b/types/ember__array/tsconfig.json new file mode 100644 index 0000000000..e6c8d509e0 --- /dev/null +++ b/types/ember__array/tsconfig.json @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "paths": { + "@ember/array": ["ember__array"], + "@ember/array/*": ["ember__array/*"] + }, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "mutable.d.ts", + "proxy.d.ts", + "types/prototype-extensions.d.ts", + "test/lib/assert.ts", + "test/array.ts", + "test/array-ext.ts", + "test/array-proxy.ts" + ] +} diff --git a/types/ember__array/tslint.json b/types/ember__array/tslint.json new file mode 100644 index 0000000000..10d875b8db --- /dev/null +++ b/types/ember__array/tslint.json @@ -0,0 +1,4 @@ +{ + "extends": "dtslint/dt.json", + "rules": {} +} diff --git a/types/ember__array/types/prototype-extensions.d.ts b/types/ember__array/types/prototype-extensions.d.ts new file mode 100644 index 0000000000..a6197166ef --- /dev/null +++ b/types/ember__array/types/prototype-extensions.d.ts @@ -0,0 +1,3 @@ +import Ember from 'ember'; + +export interface ArrayPrototypeExtensions extends Ember.MutableArray, Ember.Observable, Ember.Copyable {}