2

I'm trying to use discriminated union type in TypeScript but I'm getting the following error:

Type '{ data: Aaaa | Bbbb; type: "aaaa" | "bbbb"; }' is not assignable to type 'EventData'.
  Type '{ data: Aaaa | Bbbb; type: "aaaa" | "bbbb"; }' is not assignable to type '{ type: "bbbb"; data: Bbbb; }'.
    Types of property 'type' are incompatible.
      Type '"aaaa" | "bbbb"' is not assignable to type '"bbbb"'.
        Type '"aaaa"' is not assignable to type '"bbbb"'.

With the following code:

export type Aaaa = {
    aPropForA: string
}

export type Bbbb = {
    somePropsB: number
}

export type EventData =
  | { type: 'aaaa'; data: Aaaa }
  | { type: 'bbbb'; data: Bbbb }

// simulate getting the data for brevity
declare const data: EventData['data'];
declare const type: EventData['type'];

export const getEventData = (): EventData => {
  return { // why is there an error?
    data,
    type,
  }
}

live

What's the source of the problem? How can I fix it without typecasting?

1 Answer 1

2

The reason this is an error is that nothing guarantees that the combination of data and type is correct. In this code, the assignments are valid, and would lead to an incorrect union:

const data: EventData['data'] = { aPropForA: ""};
const type: EventData['type'] = "bbbb"

export const getEventData = (): EventData => {
  return { // why is there an error?
    data,
    type,
  }
}

The only way to get around the error without type assertions is to make the required checks:

declare const data: EventData['data'];
declare const type: EventData['type'];

export const getEventData = (): EventData => {
  if(type === 'aaaa' && 'aPropForA' in data) {
    return { data, type,}
  } else if(type === 'bbbb' && 'somePropsB' in data) { 
    return { data, type,}
  }
  throw new Error("Invalid combination")
}
Sign up to request clarification or add additional context in comments.

1 Comment

It… actually makes sense :) Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.