#Discriminated Unions not detecting type based on parameter narrowing

8 messages · Page 1 of 1 (latest)

dim mantle
#
type Cat = {
  pet: string;
  shout: (phrase: string) => void;
};

type Dog = {
  pet: string[];
  shout: (phrases: string[]) => void;
};

const me: Cat | Dog = {
  pet: ["cat", "dog"],
  shout: (n) => {
    console.log(n.length);
  },
};

I am getting Parameter 'n' implicitly has an 'any' type.ts(7006), even though it should be able to infer that n is a string[] based on the fact that pet property is string[] therefore it narrows down the type to Dog

Narrowing works fine if the pet property is a string literal. Can typescript not narrow based on property type?

violet swallow
#

yes, DUs are for when the discriminant is a distinct literal in each branch

dim mantle
#

ah okay, so it must be a literal, thank you

#

!resolved

wary nova
#

The problem is that here TS can infer that me is type Dog, and shout must be a subtype of (string[]) => void

Since function arguments are contravariant, this means

n must be of type string[] or supertype of string[] (such as string[]|number or (string|number)[])

So here n's type has lower bound, but no upper bound. It can be anything above string[]. That is why it warns implicitly any

sleek rune
violet swallow
#

a string[] is a valid string[] | number and a valid (string | number)[]

wary nova
#

A or B is super type of A

Array of (A or B)s is also super type of Array of A