Home > Mobile >  Typescript Key Issue "Type 'number' is not assignable to type 'never'."
Typescript Key Issue "Type 'number' is not assignable to type 'never'."

Time:08-15

I had looked over some other issues that were similiar to this one, however some of them had talked about modifying the tsconfig.json and changing the compiler options to include

"strictNullChecks": true,
"noImplicitAny": false,

However, my code looks like this:

export interface DetailedRankings {
show_id: number;
name: string;
category: string;
episodes: number;
story?: number;
characters?: number;
overall?: number;
}

function handleInputChange(category: keyof DetailedRankings, event: string, index: number) {
    const value_number: number = parseFloat(event);
    let list: DetailedRankings[] = [...detailed_ranks];
    let obj: DetailedRankings = list[index];
    obj[category] = value_number <--- Having issue with this.
}

I am under the impression that the reason this issue is being caused is because I have string and number within the interface. I am just a bit lost on what is causing the issue of.

Type 'number' is not assignable to type 'never'.

CodePudding user response:

The issue is that typescript cannot guarentee that the value of obj[category] is assignable number so it says that obj[category] is assignable never as it's not assignable.

A little hack you could do is just convert obj to be a type Record<string, number> or Record<keyof DetailedRankings, number>

Like this for example:

function handleInputChange(category: keyof DetailedRankings, event: string, index: number) {
    const value_number: number = parseFloat(event);
    let list: DetailedRankings[] = [...detailed_ranks];
    let obj: Record<keyof DetailedRankings, number> = list[index];
    obj[category] = value_number
}

Obviously this has the drawback of not being a DetailedRankings type anymore...

I believe it's just a drawback of strict typescript. As a programmer you know only number keys of category are passed to your function but there's no way to tell typescript that in strict mode (as far as I know)

CodePudding user response:

The issue here is that you are not restricting your function to only take keys where the type is number. This may lead to runtime errors. What is preventing me from calling the function like this?

handleInputChange("category", "0", 0)

Now obj["category"] will have a number assigned to it which breaks your interface defintion. The error is warning you from this unsoundness.

You could compute all number properties in a seperate type and use it as the argument type in your function.

type DetailedRankingsNumberProps = keyof {
  [K in keyof DetailedRankings as DetailedRankings[K] extends number 
    ? K 
    : never
  ]: K
}

function handleInputChange(
  category: DetailedRankingsNumberProps, 
  event: string, 
  index: number
) {
  const value_number: number = parseFloat(event);
  let list: DetailedRankings[] = [];
  let obj: DetailedRankings = list[index] 

  obj[category] = value_number // No error anymore
}

handleInputChange("category", "0", 0) // compile time error now

Playground

  • Related