Alwaysblue
Alwaysblue

Reputation: 11830

getting error type any is not assignable to type never

I have a state which looks like this

export interface IState {
  relationType: string
  relatedTableId: number | null
  foreignKey: string
  throughTableId: string
  required: boolean
}

and

this.state = {
  relationType: props.relation ? props.relation.relation_type : 'parent_relation',
  relatedTableId: _.get(props, 'relation.related_table.id', null),
  foreignKey: _.get(props, 'relation.foreign_key') || '',
  throughTableId: _.get(props, 'relation.through_table_id') || '',
  required: props.relation ? true :false
}

When I am trying to change state dynamically,

  handleOnChange(
    selected: ValueType<SelectOption>,
    key: 'relationType' | 'throughTableId' | 'relatedTableId'
  ) {
      const currentState = { ...this.state }
      currentState[key] = (selected as SelectOption).value;
      this.setState({ ...currentState })
  }

Here, TS is throwing following error

Type 'string' is not assignable to type 'never'

Any idea what I could be doing wrong?

THis is what Select Option looks like (if this make any difference)

type SelectOption = {
  value: string | number
  label: string
}

This is the error

enter image description here

Upvotes: 0

Views: 590

Answers (3)

ccarton
ccarton

Reputation: 3666

Typescript is pointing out that you're not doing all the required type checks. To expand on the the other answers, TS wants to see code that looks more like:

function handleOnChange(
    selected: ValueType<SelectOption>,
    key: 'relationType' | 'throughTableId' | 'relatedTableId'
) {
    const currentState = { ...this.state }
    const selectedValue = (selected as SelectOption).value
    if (key === 'relationType' || key === 'throughTableId') {
        if (typeof selectedValue === 'string') {
            currentState[key] = selectedValue
        }
    } 
    else {
        if (typeof selectedValue === 'number') {
            currentState[key] = selectedValue       
        } 
    }
}

The above uses explicit type checks which TS understands and it should compile without errors.

Upvotes: 0

Aron
Aron

Reputation: 9248

The keys you're trying to assign a value of type string | number to are not compatible with that type. They can either be assigned string or number | null but none of them can accept string | number.

relationType: string
relatedTableId: number | null
throughTableId: string

Unless you narrow the type of selected.value to make sure you:

  1. know what type it is and
  2. assign it to a field that is compatible with the narrowed type

TypeScript won't let you assign it to any of the fields you're trying to.

EDIT

As sam256 said the reason it says "is not assignable to never" is because relationType, relatedTableId and throughTableId have no overlap in types, so there is no type of value that can be assigned to all three of them.

This wouldn't be the case if key was "relationType" | "throughTableId" for example, because in that case currentState[key] could be assigned a value of type string, because:

currentState["relationType" | "throughTableId"]: string

Upvotes: 1

sam256
sam256

Reputation: 1421

Typescript is identifying a real problem here. What if you passed handleOnChange a "selected.value" that was a string, but a "key" value of "relatedTableId"? Your function would be trying to assign a string to a number. In other words you actually have a potential type mismatch in your code which TS is flagging.

I believe the wording of the error is because TS is inferring that currentState[key] is the intersection of string and number, which is never.

Upvotes: 1

Related Questions