You can try my code in a typescript playground:

export interface A {
  label: string;
  kind: "A";
}

export interface B {
    label: `Baz ${number}`;
    kind: "B";
}

// in another file...
type SubUnion = A | B;
const createObj = (): SubUnion[] => {
  const x = true;
  const n1 = 3;
  const n2 = 5;
  const result: SubUnion[] = [
    { label: "Foo", kind: "A" },
    { label: "Bar", kind: "A" },
    {
/*
Type '{ label: string; kind: "B"; }' is not assignable to type 'SubUnion'.
  Types of property 'kind' are incompatible.
    Type '"B"' is not assignable to type '"A"'.(2322)
*/
      label: `Baz ${x ? n1 : n2}`,
      kind: "B",
    },
  ];
  return result;
};

I don't understand the last two lines of that error message. Why is it saying Type '"B"' is not assignable to type '"A"'?

Fortunately, I think I understand the first line: it's saying that label: `Baz ${x ? n1 : n2}`, is a string type, but B needs a Baz ${number} type. I've found ways to fix this, but I'm not sure if any are "the right way" to do it:

  1. const result: SubUnion[] = [
      { label: "Foo", kind: "A" },
      { label: "Bar", kind: "A" },
      {
        label: `Baz ${x ? n1 : n2}`,
        kind: "B",
      },
    ] as const;
    
  2. {
      label: `Baz ${x ? n1 : n2}`,
      kind: "B",
    } satisfies B,
    
  3. {
      label: `Baz ${x ? n1 : n2}`,
      kind: "B",
    } as const,
    
  4. {
      label: `Baz ${x ? n1 : n2}` satisfies `Baz ${number}`,
      kind: "B",
    },
    
  5. {
      label: `Baz ${x ? n1 : n2}` as const,
      kind: "B",
    },
    

I can say with some confidence that as const is not the best way to do this: it lets you use literals that don't match the type on the left-hand side of the assignment. I don't know if that means satisfies is the right way to do this, but it does seem better.

In summary: Why is this error message so confusing and is there a better way to fix the error?

0

There are 0 best solutions below