jsonapi-serializer icon indicating copy to clipboard operation
jsonapi-serializer copied to clipboard

Typescript types?

Open Aryk opened this issue 7 years ago • 16 comments

Two questions:

  1. Has anyone started writing types for the newer version of this package? Maybe we can share in this doc and/or get something up on DefinitelyTyped. I know there is ts-jsonapi but it's not being heavily used, maintained, nor is it up to date with this package.

  2. Do the maintainers have any interest in adding types directly to this package since the API isn't changing much? cc @SeyZ

Aryk avatar Apr 21 '17 22:04 Aryk

I just made this recently, I will continue and add more features as I need them (or you are welcome to do it 👍 )

declare module 'jsonapi-serializer' {

    interface ISerializerOptions {
        id?: string
        attributes: string[]
        pluralizeType?: boolean
        typeForAttribute?: ITypeForAttribute
        meta?: any
        dataMeta?: any
    }

    interface ITypeForAttribute {
        (attribute: string, object?: any)
    }

    interface IDeserializerOptions {
        id?: string
        keyForAttribute?: 'dash-case' | 'lisp-case' | 'spinal-case' | 'kebab-case' | 'underscore_case' | 'snake_case' | 'camelCase' | 'CamelCase'
    }

    interface IDeserializerConstructor {
        new(opts: IDeserializerOptions): IDeserializer
    }

    interface ISerializerConstructor {
        new(collectionName: string, opts: ISerializerOptions): ISerializer
    }

    interface IErrorConstructor {
        new(opts: IJSONAPIErrorOptions): IJSONAPIError
    }

    interface IJSONAPIError {
        errors: any[]
    }

    interface IJSONAPIErrorOptions {
        id?: string
        status?: string
        code?: string
        title?: string
        detail?: string
        source: {
            pointer?: string
            parameter?: string
        }
        links?: {
            about?: string
        }
        meta?: any
    }

    interface ISerializer {
        serialize(data: any): any
    }

    interface IDeserializer {
        deserialize(data: any, callback: ICallback): void
        deserialize(data: any): Promise<any>
    }

    interface ICallback {
        (error: Error, response: any)
    }

    export let Serializer: ISerializerConstructor
    export let Deserializer: IDeserializerConstructor
    export let Error: IErrorConstructor
}

kernel-io avatar Nov 24 '17 01:11 kernel-io

declare module 'jsonapi-serializer' {
  type RefFunction = (current: any, item: any) => string;

  export interface IRelation {
    ref: string | RefFunction;
    attributes?: string[];
    included?: boolean;
  }

  interface ISerializerOptions {
    id?: string;
    attributes: string[];
    pluralizeType?: boolean;
    typeForAttribute?: ITypeForAttribute;
    meta?: any;
    dataMeta?: any;
  }

  interface ITypeForAttribute {
    (attribute: string, object?: any): any;
  }

  interface ITransform {
    (record: any): any;
  }

  interface IDeserializerOptions {
    id?: string;
    keyForAttribute?: 'dash-case' | 'lisp-case' | 'spinal-case' | 'kebab-case' | 'underscore_case' | 'snake_case' | 'camelCase' | 'CamelCase';
    pluralizeType?: boolean;
    typeAsAttribute?: boolean;
    transform?: ITransform;
  }

  interface IDeserializerConstructor {
    new(opts: IDeserializerOptions): IDeserializer;
  }

  interface ISerializerConstructor {
    new(collectionName: string, opts: ISerializerOptions): ISerializer;
  }

  interface IErrorConstructor {
    new(opts: IJSONAPIErrorOptions): IJSONAPIError;
  }

  interface IJSONAPIError {
    errors: any[];
  }

  interface IJSONAPIErrorOptions {
    id?: string;
    status?: string;
    code?: string;
    title?: string;
    detail?: string;
    source: {
      pointer?: string
      parameter?: string,
    };
    links?: {
      about?: string,
    };
    meta?: any;
  }

  interface ISerializer {
    serialize(data: any): any;
  }

  interface IDeserializer {
    deserialize(data: any, callback: ICallback): void;

    deserialize(data: any): Promise<any>;
  }

  interface ICallback {
    (error: Error, response: any): any;
  }

  // noinspection TsLint
  export let Serializer: ISerializerConstructor;
  // noinspection TsLint
  export let Deserializer: IDeserializerConstructor;
  // noinspection TsLint
  export let Error: IErrorConstructor;
}

little bit extended variant

alexkvak avatar Sep 24 '18 14:09 alexkvak

Maybe you could submit a PR to Definitely Typed ?

johannesschobel avatar Nov 11 '18 15:11 johannesschobel

Made a few additions to ISerializerOptions above:

declare module 'jsonapi-serializer' {
  type RefFunction = (current: any, item: any) => string;

  export interface IRelation {
    ref: string | RefFunction;
    attributes?: string[];
    included?: boolean;
  }

  interface ISerializerOptions {
    ref?: Function | boolean | string;
    included?: boolean;
    id?: string;
    attributes?: string[];
    topLevelLinks?: string[] | Function[];
    dataLinks?: string[] | Function[];
    dataMeta?: Function | object;
    relationshipLinks?: object;
    relationshipMeta?: object;
    ignoreRelationshipData?: boolean;
    keyForAttribute?: string | IKeyForAttribute;
    nullIfMissing?: boolean;
    pluralizeType?: boolean;
    typeForAttribute?: ITypeForAttribute;
    meta?: object;
    transform?: Function;
  }

  interface IKeyForAttribute {
    (attribute: string): string;
  }

  interface ITypeForAttribute {
    (attribute: string, object?: any): any;
  }

  interface ITransform {
    (record: any): any;
  }

  interface IDeserializerOptions {
    id?: string;
    keyForAttribute?:
      | 'dash-case'
      | 'lisp-case'
      | 'spinal-case'
      | 'kebab-case'
      | 'underscore_case'
      | 'snake_case'
      | 'camelCase'
      | 'CamelCase';
    pluralizeType?: boolean;
    typeAsAttribute?: boolean;
    transform?: ITransform;
  }

  interface IDeserializerConstructor {
    new (opts: IDeserializerOptions): IDeserializer;
  }

  interface ISerializerConstructor {
    new (collectionName: string, opts: ISerializerOptions): ISerializer;
  }

  interface IErrorConstructor {
    new (opts: IJSONAPIErrorOptions): IJSONAPIError;
  }

  interface IJSONAPIError {
    errors: any[];
  }

  interface IJSONAPIErrorOptions {
    id?: string;
    status?: string;
    code?: string;
    title?: string;
    detail?: string;
    source: {
      pointer?: string;
      parameter?: string;
    };
    links?: {
      about?: string;
    };
    meta?: any;
  }

  interface ISerializer {
    serialize(data: any): any;
  }

  interface IDeserializer {
    deserialize(data: any, callback: ICallback): void;

    deserialize(data: any): Promise<any>;
  }

  interface ICallback {
    (error: Error, response: any): any;
  }

  // noinspection TsLint
  export let Serializer: ISerializerConstructor;
  // noinspection TsLint
  export let Deserializer: IDeserializerConstructor;
  // noinspection TsLint
  export let Error: IErrorConstructor;
}

If I find time, I'll try to submit a PR to DT.

chiangf avatar Dec 07 '18 17:12 chiangf

@chiangf what is the status of this?

johannesschobel avatar Jan 09 '19 15:01 johannesschobel

@johannesschobel just pushed a PR into dt

chiangf avatar Jan 11 '19 02:01 chiangf

Thanks

johannesschobel avatar Jan 11 '19 05:01 johannesschobel

We should be able to resolve this issue now that https://github.com/DefinitelyTyped/DefinitelyTyped/pull/32057 has been merged 👍

chiangf avatar Jan 22 '19 13:01 chiangf

Dear @chiangf ,

i have a question regarding your typings.. I was trying to add relationships to a serializer, however, i did not manage to solve this issue. Here is my code so far:

    const serializer = new Serializer('users', {
      attributes: ['username', 'email', 'createdAt', 'updatedAt', 'projects'],
      keyForAttribute: 'camelCase',

      projects: {
        ref: 'id',
        included: true,
        attributes: ['name', 'description'],
      }
    });

The IDE indicates the projects with the red squiggly lines, saing that there is no property projects in the SerializerOptions.

Unfortunately, i was not able to add an [prop: string]?: Relation property to the SerializerOptions to "fix" this.. How do you manage to add relations?

All the best

johannesschobel avatar Mar 06 '19 14:03 johannesschobel

I am using "@types/jsonapi-serializer": "^3.6.2", shouldn't the default opts constructor parameter be nullable for Deserializer?

By example in the README I see that it is optional.

jelovac avatar Sep 14 '19 07:09 jelovac

@johannesschobel, I've added [key: string]: Relation | any; locally, to avoid these errors. Not the best solution, so if someone will be able to provide a better one that would be great! If not, I will send a PR later.

bvenchak avatar Oct 03 '19 14:10 bvenchak

export interface SerializerOptions {
    ref?: (() => void) | boolean | string;
    included?: boolean;
    id?: string;
    attributes?: string[];
    topLevelLinks?: string[] | Array<() => void>;
    dataLinks?: string[] | Array<() => void>;
    dataMeta?: (() => void) | object;
    relationshipLinks?: object;
    relationshipMeta?: object;
    ignoreRelationshipData?: boolean;
    keyForAttribute?: string | KeyForAttribute;
    nullIfMissing?: boolean;
    pluralizeType?: boolean;
    typeForAttribute?: TypeForAttribute;
    meta?: object;
    transform?: (() => void);
}

Is it correct that the dataLinks property is an array?

OlexandrPopov avatar Dec 30 '19 16:12 OlexandrPopov

We're also missing something like:

export interface SerializerOptions {
    [key: string]: {
        valueForRelationship: (relationship) => any
        transform: (obj: any) => any
    };
}

kristof-mattei avatar Apr 23 '20 05:04 kristof-mattei

The way this function is written in JS makes it really hard to make a TS definition that's able to infer the types.

https://github.com/basarat/typescript-book/blob/master/docs/types/index-signatures.md#excluding-certain-properties-from-the-index-signature Meaning if we update the definition to

type DeserializerExtras<T extends string> = {
    [key in T]: {
        valueForRelationship: (relationship: any) => { id: string };
        transform: (o: any) => any;
    }
}

export interface DeserializerConstructor {
    new<T extends string>(opts: DeserializerOptions & DeserializerExtras<T>): Deserializer;
}

We have to explicitly write down the properties not part of DeserializerOptions that we would like to use:

JSONAPIDeserializer.Deserialize<'address' | 'origin'>({
    keyForAttribute: "camelCase",
    address: (addressRel) => addressRel.id;
    origin: (originRel) => originRel.id;
}

If we don't do that, the code will complain that keyForAttribute doesn't match our DeserializerExtras signature.

kristof-mattei avatar May 15 '20 04:05 kristof-mattei

some update about relationship?

jairmedeiros avatar May 07 '21 06:05 jairmedeiros

@jairmedeiros topic was open in 2017, still no luck to this day ; it's fair to say @SeyZ is probably busy with something else or has let go of this lib.

y-nk avatar Aug 29 '21 12:08 y-nk