Hunter
Hunter

Reputation: 57

Why this syntax Object[key] show error in typescript ? how should I read properties from an object?

I would like to create one request map , that would some like one api request url config, then I could easy like send out a request just like ,sendRequest(name,body). but this is some syntax error in typescript? it very strange

class HttpRequest {
baseURL = "http://localhost:8080" // get this by env later
requestMap = {
    "city":{
        method:"GET",
        url: this.baseURL+"/area/city" ,
    }

}

getRequest(requestName: String, body: object | null, params:null|object) {
   return axios({
        method:this.requestMap[String(requestName)]["method"],
        url: this.requestMap[requestName]["url"] ,
        params: params? params: null,
        data:body? body:null
    })
}

Upvotes: 2

Views: 53

Answers (1)

Thomaz Capra
Thomaz Capra

Reputation: 1053

I suppose you are getting this error: Type 'String' cannot be used as an index type, right?

You are getting this error because Typescript forces you to use a valid type for indexing an object, requestMap has only one property, called 'city', when you try to do this.requestMap[String(requestName)]["method"], Typescript is telling you that String cannot index requestMap, and it is totally right about it, the method only exist in the city property.

To fix it, you can do any of those things:

Or changing the type of the requestName param to 'city':

 class HttpRequest {
  baseURL = "http://localhost:8080"; // get this by env later
  requestMap = {
    city: {
      method: "GET",
      url: this.baseURL + "/area/city",
    },
  };

  getRequest(requestName: 'city', body: object | null, params: null | object) {
    return axios({
      method: this.requestMap[requestName]["method"],
      url: this.requestMap[requestName]["url"],
      params: params ? params : null,
      data: body ? body : null,
    });
  }
}

Or, if you want some flexibily, you can create a type with all possible properties of the requestMap, somethings like this (when you know exacly what properties the object can have):

type RequestProps = "city" | "country";
type RequestPropsType = {
  method: string;
  url: string;
};

class HttpRequest {
  baseURL = "http://localhost:8080"; // get this by env later
  requestMap: Record<RequestProps, RequestPropsType> = {
    city: {
      method: "GET",
      url: this.baseURL + "/area/city",
    },
    country: {
      method: "GET",
      url: this.baseURL + "/area/country",
    },
  };

  getRequest(
    requestName: RequestProps,
    body: object | null,
    params: null | object
  ) {
    return axios({
      method: this.requestMap[requestName]["method"],
      url: this.requestMap[requestName]["url"],
      params: params ? params : null,
      data: body ? body : null,
    });
  }
}

But if you want full flexibity, making the requestMap be indexed by any string, you can change the String to string, but in this case, is not guaranteed the property will exist, so you should use the optional chaining operator (available since typescript v3.7) to avoid accessing functions of undefined:

class HttpRequest {
  baseURL = "http://localhost:8080"; // get this by env later
  requestMap = {
    city: {
      method: "GET",
      url: this.baseURL + "/area/city",
    },
  };

  getRequest(
    requestName: string,
    body: object | null,
    params: null | object
  ) {
    return axios({
      method: this.requestMap[requestName]?.["method"],
      url: this.requestMap[requestName]?.["url"],
      params: params ? params : null,
      data: body ? body : null,
    });
  }
}

Upvotes: 3

Related Questions