#Union issues?

1 messages · Page 1 of 1 (latest)

still flame
#

i think im confused about how/why typescript isnt handling narrowing my union:

type CreatedGame = { state: number; code: string }
type InitialGame = { state: number; }
type MessageIn = CreatedGame | InitialGame

there's some surrounding svelte code, but when i try to pass a handler variable with type (data: CreatedGame) => void into a component that accepts a handler prop with type (data: MessageIn) => void i get the error:

Type '(data: CreatedGame) => void' is not assignable to type '(data: MessageIn) => void'.
  Types of parameters 'data' and 'data' are incompatible.
    Type 'MessageIn' is not assignable to type 'CreatedGame'.
      Property 'code' is missing in type 'InitialGame' but required in type 'CreatedGame'.

why?
like in my head it works as "i want a component that takes a prop that can be any of the MessageIn types, so I could initialise the component either with a CreatedGame or an InitialGame"

rich hamlet
#

and so the parameter must be equal or wider

limber cliff
#

this might be what bean meant, but your (data: CreatedGame) => void function is allowed to access data.code, but the caller is allowed to pass a InitialGame which won't have a .code property

still flame
rich hamlet
#

(data: MessageIn) => void accepts an InitialGame, which your actual function (data: CreatedGame) => void cannot handle

limber cliff
#

!:variance

lapis terraceBOT
#
tjjfvi#0
`!t6:variance`:

Here's the example with Dog and Animal, explaining co/contra/in variance:

  • Covariance: () => Dog is assignable to () => Animal, because Dog is assignable to Animal; it "preserves the direction of the assignability"
  • Contravariance: (Animal) => void is assignable to (Dog) => void, because something that expects an Animal can also take a Dog; it "reverses the direction of the assignability"
  • Invariance: (Animal) => Animal is not assignable to (Dog) => Dog, because not all returned Animals are Dogs, and (Dog) => Dog is not assignable to (Animal) => Animal, because something expecting a Dog cannot take any other kind of Animal
limber cliff
#

here's an example you can play with. you can run it and see the runtime error that typescript is trying to save you from