diff --git a/types/ember-data/index.d.ts b/types/ember-data/index.d.ts index e3917b1a8b..2a2fdab7bd 100644 --- a/types/ember-data/index.d.ts +++ b/types/ember-data/index.d.ts @@ -13,6 +13,32 @@ declare module 'ember-data' { export interface ModelRegistry {} export interface AdapterRegistry {} export interface SerializerRegistry {} + export interface TransformRegistry { + 'string': string; + 'boolean': boolean; + 'number': number; + 'date': Date; + } + + type AttributesFor = keyof Model; // TODO: filter to attr properties only (TS 2.8) + type RelationshipsFor = keyof Model; // TODO: filter to hasMany/belongsTo properties only (TS 2.8) + + interface AttributeMeta { + type: keyof TransformRegistry; + options: object; + name: AttributesFor; + parentType: Model; + isAttribute: true; + } + interface RelationshipMeta { + key: RelationshipsFor; + kind: 'belongsTo' | 'hasMany'; + type: keyof ModelRegistry; + options: object; + name: string; + parentType: Model; + isRelationship: true; + } namespace DS { /** @@ -82,27 +108,11 @@ declare module 'ember-data' { * `boolean` and `date`. You can define your own transforms by subclassing * [DS.Transform](/api/data/classes/DS.Transform.html). */ - function attr( - type: 'string', - options?: AttrOptions - ): Ember.ComputedProperty; - function attr( - type: 'boolean', - options?: AttrOptions - ): Ember.ComputedProperty; - function attr( - type: 'number', - options?: AttrOptions - ): Ember.ComputedProperty; - function attr( - type: 'date', - options?: AttrOptions - ): Ember.ComputedProperty; - function attr( - type: string, - options?: AttrOptions - ): Ember.ComputedProperty; - function attr(options?: AttrOptions): Ember.ComputedProperty; + function attr( + type: K, + options?: AttrOptions + ): Ember.ComputedProperty; + function attr(options?: AttrOptions): Ember.ComputedProperty; /** * WARNING: This interface is likely to change in order to accomodate https://github.com/emberjs/rfcs/pull/4 * ## Using BuildURLMixin @@ -942,7 +952,7 @@ declare module 'ember-data' { /** * Returns the value of an attribute. */ - attr(keyName: L): ModelRegistry[K][L]; + attr>(keyName: L): ModelRegistry[K][L]; /** * Returns all attributes and their corresponding values. */ @@ -954,18 +964,18 @@ declare module 'ember-data' { /** * Returns the current value of a belongsTo relationship. */ - belongsTo( + belongsTo>( keyName: L, options?: {} ): Snapshot['record'][L] | string | null | undefined; /** * Returns the current value of a hasMany relationship. */ - hasMany( + hasMany>( keyName: L, options?: { ids: false } ): Array['record'][L]> | undefined; - hasMany( + hasMany>( keyName: L, options: { ids: true } ): string[] | undefined; @@ -973,12 +983,12 @@ declare module 'ember-data' { * Iterates through all the attributes of the model, calling the passed * function on each attribute. */ - eachAttribute(callback: Function, binding: {}): any; + eachAttribute(callback: (key: keyof M, meta: AttributeMeta) => void, binding?: {}): any; /** * Iterates through all the relationships of the model, calling the passed * function on each relationship. */ - eachRelationship(callback: Function, binding: {}): any; + eachRelationship(callback: (key: keyof M, meta: RelationshipMeta) => void, binding?: {}): any; /** * Serializes the snapshot using the serializer for the model. */ diff --git a/types/ember-data/test/serializer.ts b/types/ember-data/test/serializer.ts index baaa65ae9e..b694b38b89 100644 --- a/types/ember-data/test/serializer.ts +++ b/types/ember-data/test/serializer.ts @@ -37,3 +37,59 @@ const EmbeddedRecordMixin = DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { } } }); + +class Message extends DS.Model.extend({ + title: DS.attr(), + body: DS.attr(), + + author: DS.belongsTo('user'), + comments: DS.belongsTo('comment') +}) {} + +declare module 'ember-data' { + interface ModelRegistry { + 'message-for-serializer': Message; + } +} + +interface CustomSerializerOptions { + includeId: boolean; +} + +const SerializerUsingSnapshots = DS.RESTSerializer.extend({ + serialize(snapshot: DS.Snapshot<'message-for-serializer'>, options: CustomSerializerOptions) { + let json: any = { + POST_TTL: snapshot.attr('title'), + POST_BDY: snapshot.attr('body'), + POST_CMS: snapshot.hasMany('comments', { ids: true }) + }; + + if (options.includeId) { + json.POST_ID_ = snapshot.id; + } + + return json; + } +}); + +DS.Serializer.extend({ + serialize(snapshot: DS.Snapshot<'message-for-serializer'>, options: {}) { + let json: any = { + id: snapshot.id + }; + + snapshot.eachAttribute((key, attribute) => { + json[key] = snapshot.attr(key); + }); + + snapshot.eachRelationship((key, relationship) => { + if (relationship.kind === 'belongsTo') { + json[key] = snapshot.belongsTo(key, { id: true }); + } else if (relationship.kind === 'hasMany') { + json[key] = snapshot.hasMany(key, { ids: true }); + } + }); + + return json; + }, +});