0

I read in this post that I could use fromObject in HttpParamsOptions to use an object as my query parameters on a query. Unfortunately I'm having some issues getting the Object to be in the right shape. I thought that it would be able to consume an object that had all strings for types and am not sure how to cast it into the right shape. I'd prefer not to have to iterate over object keys to get things to fit into this box - it loses all its value if I have to do that.

Can anyone explain to me what's going on here? I've read about the indexable types but that didn't help me figure out how to apply that to this case.

Type error reported:

TS2322: Type '{ fromObject: Query; }' is not assignable to type 'HttpParamsOptions'. 
  Types of property 'fromObject' are incompatible.
    Type 'Query' is not assignable to type '{ [param: string]: string | string[]; }'.
      Index signature is missing in type 'Query'.

Call site (started with {params: query} in the get and decomposed to this):

public retrieve(query: Query): Observable<PolicyRetrieveResult> {
  const q: HttpParamsOptions = {fromObject: query};
  const params = new HttpParams(q);
  return this.http.get<Result>(url, {params: params});
}

My query class:

export class Query {
  id: string;
  source: string = 'constant';
  type: string = 'otherConstant';
}

Here is HttpParamsOptions for reference:

export interface HttpParamsOptions {
    /**
     * String representation of the HTTP params in URL-query-string format. Mutually exclusive with
     * `fromObject`.
     */
    fromString?: string;
    /** Object map of the HTTP params. Mutally exclusive with `fromString`. */
    fromObject?: {
        [param: string]: string | string[];
    };
    /** Encoding codec used to parse and serialize the params. */
    encoder?: HttpParameterCodec;
}
Brian
  • 2,253
  • 2
  • 23
  • 39
  • HttpParamsOptions is not a public angular type. You're not supposed to use it. What are you trying to achieve? – JB Nizet Jul 06 '18 at 13:13
  • I'm trying to achieve this: this.http.get(url, {params: query}); where query is a class I've defined – Brian Jul 06 '18 at 13:35

1 Answers1

2

Since you have strings, to make it simle, I suggest you do something like this instead :

public retrieve(query: Query): Observable<PolicyRetrieveResult> {
  return this.http.get<Result>(url, {params: {...query}});
}

In the future, if you have non string object,s the correct syntax is

params: HttpParams = new HttpParams({ fromObject: query })

Don't use HttpParamsOptions, when you see where it comes from you'll understand why :

import { HttpParamsOptions } from '@angular/common/http/src/params';
  • The new HttpParams has the same exception as above ```TS2345: Argument of type '{ fromObject: Query; }' is not assignable to parameter of type 'HttpParamsOptions'. Types of property 'fromObject' are incompatible. Type 'Query' is not assignable to type '{ [param: string]: string | string[]; }'. Index signature is missing in type 'Query'.``` – Brian Jul 06 '18 at 13:38
  • Type it as any, and did you try the first solution ? –  Jul 06 '18 at 13:40
  • 2
    It should be `{params: { ...query } }` – JB Nizet Jul 06 '18 at 13:42
  • With the spread operator? Yeah it didn't like it. From what I've read it should work even without the spread operator but I get that bracketed type error no matter where i put params: query. Grabbing the error from the spread operator now – Brian Jul 06 '18 at 13:43
  • Oh, my bad, I didn't see I forgot one set of brackets ! And it works because it's the correct syntax, the spread operator deconstructs an object. That's the equivalent of re writing all the properties by hand, so you need to surround it with brackets as if it was an object. I edited my answer, thank you for the amend ! –  Jul 06 '18 at 13:53
  • So why does spread + new object satisfy the requirements of fromObject. I'm still trying to wrap my head around why the naked object doesn't work but an identical anonymous object does – Brian Jul 06 '18 at 13:53
  • It says why in your error : type mismatch. The options have a signature, your query interface has an other. Spreading the object probably removes the interface from it. What you could do is create a type like this : `retrieve(query: {[key: string in Query]: string})`, which should be a workaround to your issue. –  Jul 06 '18 at 13:58
  • @trichetriche I understand the error message. but it seems like i wouldn't be able to create a typescript class that matches this - which seems asinine for a typescript first interface on a parameter called fromObject. I'm very green in the js world so maybe i can make a class that satisfies this constraint. – Brian Jul 09 '18 at 12:40
  • Yes, use this : `retrieve(query: {[key: string in Query]: string})`. This will force you to give a parameter only made of keys that are in your `Query` interface. –  Jul 09 '18 at 12:49