HelloWorld
HelloWorld

Reputation: 11249

Optional parameter is type checked and errors with type guard

I am new to typescript, I apologize if my lingo for the language is off.

I want to make a generic function that optionally has an OAUTH token passed to it.

Here is my attempt:

import { AxiosStatic } from 'axios'

export function createAxiosInstance(
  axiosFactory: AxiosStatic,
  baseUrl: string,
  apiKey: string,
  clientId: string,
  clientSecret: string,
  authorization?: string | undefined
) {
  const headers = authorization
    ? {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      'X-Api-Key': apiKey,
      Authorization: authorization
    }
    : {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      'X-Api-Key': apiKey
    }
  return axiosFactory.create({
    baseURL: baseUrl,
    headers
  })
}

The headers object either has the Authorization property or it doesn't based on the parameter.

However, the headers object in the return statement within axiosFactory.create is throwing a typescript error:

Type '{ Accept: string; 'Content-Type': string; 'X-Api-Key': string; Authorization: string; } | { Accept: string; 'Content-Type': string; 'X-Api-Key': string; Authorization?: undefined; }' is not assignable to type 'AxiosRequestHeaders | undefined'. Type '{ Accept: string; 'Content-Type': string; 'X-Api-Key': string; Authorization?: undefined; }' is not assignable to type 'AxiosRequestHeaders'. Property 'Authorization' is incompatible with index signature. Type 'undefined' is not assignable to type 'string | number | boolean'.

Here is the tsconfig.json file:

{
  "compileOnSave": false,
  "compilerOptions": {
    "rootDir": ".",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "importHelpers": true,
    "target": "es2015",
    "module": "esnext",
    "lib": ["es2017", "dom"],
    "skipLibCheck": true,
    "skipDefaultLibCheck": true,
    "baseUrl": ".",
    "strictNullChecks": true
  },
  "exclude": ["node_modules", "tmp"],
  "ts-node": {
    "compilerOptions": {
      "module": "commonjs"
    }
  }
}

The axios library I'm using has the AxiosRequestHeaders defined and it appears Authorization can only be string | number | boolean. In my scenario, Authorization can be undefined. I thought the type check (checking the value of authorization) would have resolved this since I never consume authorization as undefined however this hasn't resolved the typescript error. Any ideas on how to resolve this?

Upvotes: 0

Views: 141

Answers (1)

HelloWorld
HelloWorld

Reputation: 11249

Adding the AxiosRequestHeaders type to the headers variable solved the type error.

import { AxiosRequestHeaders, AxiosStatic } from 'axios'

export function createAxiosInstance(
  axiosFactory: AxiosStatic,
  baseUrl: string,
  apiKey: string,
  clientId: string,
  clientSecret: string,
  authorization?: string | undefined
) {
  const headers: AxiosRequestHeaders = authorization
    ? {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      'X-Api-Key': apiKey,
      Authorization: authorization
    }
    : {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      'X-Api-Key': apiKey
    }
  return axiosFactory.create({
    baseURL: baseUrl,
    headers
  })
}

Without adding the type to headers, this is what was inferred:

enter image description here

Adding the type: const headers: AxiosRequestHeaders = authorization infers this:

enter image description here

As mentioned in some comments, there is likely more going on in my tsconfig that caused this, my original solution worked in a basic config.

Upvotes: 0

Related Questions