diff --git a/CHANGELOG.md b/CHANGELOG.md index 53d8ae1..466f1df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.10.2 + +- deprecates `attrs` +- no longer deprecating `decodeArray` due to usage frequency + ## 1.10.0 - new way to extend type to a class: `Model` diff --git a/README.md b/README.md index 4d19a01..18b31bd 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,7 @@ export interface User { // Step 2. add `schema()` to the manifest to register import { schema, Decoder } from 'io-interface'; -const schemas = [ - //... - schema(), -]; - -export const decoder = new Decoder(schemas); +export const decoder = new Decoder([schema()]); // src/app/users/user.service.ts // Step 3. use `decode()` and `decodeArray()` to do the validation/conversion. @@ -134,6 +129,19 @@ export const casters = { }; ``` +Usage: + +```typescript +import { casters } from 'io-interface/types'; + +const dec = new Decoder( + [ + /* schemas */ + ], + casters, +); +``` + ### Enum types You can easily register an enum using `enumSchema` @@ -150,67 +158,9 @@ decoder.register(enumSchema('Status', Status)); const status = decoder.decode('Status', 'pending'); ``` -### Attach custom values - -Sometimes you want attach some custom values onto the object. You can do it via the magical attribute `attrs`. If a field of the interface is named `attrs`, it will bypass the validation and be assigned as an empty object. So you should declare all fields inside `attrs` as **optional** since they're empty from the data source in the first place. - -```typescript -interface Compound { - lat: number; - lng: number; - attrs: { - // it will be an empty object after decoding - marker?: google.maps.Marker; // mark it as optional - }; -} - -// ... -api.requestAndCast(url).subscribe(compound => { - // here: compound.attrs === {} -}); - -// ... - -// after some biz logic ... -compound.attrs.marker = new google.maps.Marker(); -// ... -``` - -So we have clear vision that which of the fields are from the data source and which of them are added later on. - -But please do **NOT** use this feature to do name mapping like: - -```typescript -// do NOT do this!!! -interface Order { - user_uid: string; - attrs: { - userUid: string; - }; -} -``` - -This feature is only used to attach new values. Tasks like name mapping should live inside a middleware. And feature request for this is welcomed (but without guarantee that it will be implemented soon). - ### Extending the interface -The Decoder can convert the outcome to an instance if you register with a `Builder` object: - -```typescript -decoder.register({ - schema: schema(), - constructor: Guest, - className: 'Guest', -}); - -const guest = decoder.decode('Guest', data); - -// the above line is equivalent to -const iGuest = decoder.decode('IGuest', data); -const guest = new Guest(iGuest); -``` - -You may subclass `Model` to extend the interface: +You may subclass `Model` to extend the interface to a class: ```typescript import { Model } from 'io-interface'; @@ -292,6 +242,7 @@ The example code is as follows. ```typescript import { Injectable } from '@angular/core'; import { Decoder, schema } from 'io-interface'; +import { casters } from 'io-interface/types'; import { BadTodo } from '../models/bad-todo'; import { Todo } from '../models/todo'; @@ -301,7 +252,7 @@ import { Todo } from '../models/todo'; export class DecoderService { readonly schemas = [schema(), schema()]; - readonly dec = new Decoder(this.schemas); + readonly dec = new Decoder(this.schemas, casters); decode(typeName: string, data: unknown): T | undefined { return this.dec.decode(typeName, data, console.error); diff --git a/index.ts b/index.ts index f88cb94..813015d 100644 --- a/index.ts +++ b/index.ts @@ -91,6 +91,7 @@ const LiteralTypeC: t.Type = t.type({ * * The Decoder will think it as "any" and assign an empty * object to it. + * @deprecated use Model instead * @since 1.5.0 * @example * interface User { @@ -238,7 +239,7 @@ export class Decoder implements ICaster { } /** - * @deprecated use decode({ type: 'Array', arg: T }, data, onError) + * A shortcut to decode({ type: 'Array', arg: T }, data, onError) * @since 1.1.0 */ decodeArray(