#Why cannot it infer the type from union?

21 messages · Page 1 of 1 (latest)

devout steeple
#
export type ITreeNode1 = {
  value: {
    method: number;
    enabled: boolean
  }
};

export type ITreeNode2 = {
  value: {
    age: number
    enabled: boolean
  }
};

export type ITreeNode3 = {
  value: {
    name: string
  }
};
export type SelectedNode = ITreeNode1 | ITreeNode2 | ITreeNode3;

const example = (n: SelectedNode) => {
if ("value" in n && "enabled" in n.value) {
  const node = n; // still shows SelectedNode type, cannot infer that is either TreeNode1 or TreeNode2?
}
}
severe badge
#

the "enabled" in n.value check narrows n.value, but not n

frozen ocean
#

If you've got control over the data-structure writing this as a discriminated union would be a lot easier than doing in checks

#

!hb discriminated union

devout steeple
#

i did something like this:

export const hasEnabledField = (node: UNodeTypes): node is Extract<UNodeTypes, {value: {enabled: boolean}}> => {
  return "value" in node && "enabled" in node.value
}
severe badge
severe badge
devout steeple
severe badge
#

it makes it controllable

devout steeple
# severe badge it makes it controllable

but if i make NodeTree3 have "enabled" field then i will have to add the check to the function manually and it wouldnt give any warnings if i forgot to do it, right?

Or am i missing something

severe badge
#

yeah that's correct

devout steeple
#

well i guess thats not really great for my use case then

frozen ocean
#

Or you could eliminate the cases that don't have the property:

function example(node: TreeNode) {
  // Ignore the cases that *don't* have enabled
  if(node.kind === "node3") return;
  // Will compile error if you add a new kind that doesn't have enabled and don't add it above
  console.log(node.value.enabled);
}
#

But yeah, the special type-guard with Extract is fine too, but it would quickly grow annoying if you had a lot of those.

devout steeple
frozen ocean
#

I mean if you write hasEnabledField and hasOtherField and hasYetAnotherField that's a lot of very specific utilities that you have to make sure the unchecked type is correct on. Maybe that's not realistic, I don't know what your problem domain looks like

devout steeple
frozen ocean
#

I guess for me writing specific checks the place I'm doing checks is less annoying than having a bunch of utility type-guards with complex type signatures; but I guess it just depends on what you're doing