0

I have a state, interface , and a function that process the API data

  • const [series, setSeries] = useState<ISeries[]>([])

export interface ITicket {
  status?: string
  status_desc?: string
  keyword_language?: string
}

interface ISeries {
  colorByPoint: boolean
  data: {
    name: string
    y: number
    status: string | undefined
    keyword_language: string | undefined
  }[]
}

function that process the api Data

function trans(series: ITicket[]) {

  const data = series.map(s => {

    return {
**//api only reuturn either s.status_desc or s.keyword_language, only one** 
      name: s.status_desc ? s.status_desc : s.keyword_language,
      y: s.ticket_count,
      status: s?.status,
      keyword_language: s?.keyword_language,

    }
  })

  return [
    {
      colorByPoint: true,
      data,
    },
  ]
}

In the function that process the API data, I am checking what value was passed in order to set the name property.

    return {
**//api only reuturn either s.status_desc or s.keyword_language, only one** 
      name: s.status_desc ? s.status_desc : s.keyword_language, 

But then I get a TypeScript compilor error that it is not assignable since name must be a string. Now there is chance that it can be undefined.

Question:

I am sure that API will pass either s.status_desc or s.keyword_language as a string. So name will get a string value to assign.

I dont want to change the type for name to string | undefined

I don't want to use TypeScript ignore (@ts-ignore) to by pass the error.

How can I get rid of the error without faking?

bear in mind: in the interface, I cant change the type of status_desc and keyword_language in order to bypass it because API could either pass me one. So I have to keep the type as undefined for both cases

Dimitri Kopriwa
  • 13,139
  • 27
  • 98
  • 204
  • What about casting with `as` ? – Dimitri Kopriwa Jul 11 '22 at 14:28
  • This just solve the typescript issue and make the code less readable because we don't get why this was added as it will never reach the last empty string value. I propose a comment to explain why we string cast `name` – Dimitri Kopriwa Jul 11 '22 at 14:34
  • Note that there is nothing in the code that prevents both `status_desc` *and* `keyword_language` from being undefined; your ternary won't solve that. I suggest using the nullish coalescing operator: `name: s.status_desc ?? s.keyword_language ?? ""` unless you know your service will always return one or the other. Note that it is possible to defined one or the other as undefined: see [typescript interface require one of two properties to exist](https://stackoverflow.com/q/40510611/215552) – Heretic Monkey Jul 11 '22 at 14:42

4 Answers4

0

I would suggest to just cast the variable and add a comment like so:

{
  // Cast because server will always serv a string for at least one of the two
  name: (s.status_desc || s.keyword_language) as string,
}
Dimitri Kopriwa
  • 13,139
  • 27
  • 98
  • 204
  • let say, the s.status_desc was not returned, and only s.keyword_language returned. Then (s.status_desc || s.keyword_language) become true..... s.status_desc is underfine and keyword have sth , Will it become a true-false statement? –  Jul 11 '22 at 14:41
  • But I will to assign a value of string instead of yes/no 1/0 –  Jul 11 '22 at 14:42
  • what do you think this kind of problem is classified as javascript problem or typescript problem ? –  Jul 11 '22 at 14:46
  • @Sergey Sosunov explained why –  Jul 11 '22 at 14:47
0

Simplest way: name: s.status_desc || s.keyword_language || ""

console.log(null || undefined || "" || "asd" || ""); will print "asd"

return {
    name: s.status_desc || s.keyword_language || "",
    y: s.ticket_count,    
    status: s.status,
    keyword_language: s?.keyword_language,
}

So if by any chance both fields are null or undefined - your code will not fail with error trying to access null field name (it will be an empty string)

Or you can use Non-Null Assertion Operator !:

Considered as a bad practice but can help anyway.

name: s.status_desc! || s.keyword_language!
Sergey Sosunov
  • 4,124
  • 2
  • 11
  • 15
  • Is there are name to call such sytanx? :Simplest way: name: s.status_desc || s.keyword_language || "" –  Jul 11 '22 at 18:04
  • 1
    Not sure if that syntax has a name, but here is an explanation about what is it and how it works https://stackoverflow.com/a/3088498/5767872 – Sergey Sosunov Jul 11 '22 at 18:21
0

Basically you may simply cast it.

as string.

Then typescript, you may think of it as compiler check, will see it as string

0

You may cast it like this:

name: (s.status_desc || s.keyword_language) as string,

The understanding of the || here is a bit different from traditional understanding.

for your reference: JavaScript OR (||) variable assignment explanation

Ae Leung
  • 300
  • 1
  • 12