Skip to content

Omit<UnionType, "NonDiscriminatedKey"> cause failure in destructed typeΒ #63294

@yarden-app

Description

@yarden-app

πŸ”Ž Search Terms

Distributive types, conditional

πŸ•— Version & Regression Information

Always

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/PTBQIAgIQQwZwJYGMIBcCeAHAphAJtgGYIB2CqCA9iRCOGBjhAIIQC8908ujuzADBAAW8CAEkAIhBgk8EACrkANtlAQWggGRrawCBIRwkAJwQBbUjFTY5vOAAoARtznUIAcl7uImY5RzGGACUEIR+ZiwAjNKyLABMOvbM0QA+8UGgoLwa7BAA3jqSAFwQcKimJADmANw6iqgqJWUVNboQADwAtJ3i0ngEtkK4AET1KsPScNIQZtjwAK7GPJQQ2CRwizwiqBAA8hao7cwANMOSwwB8EADu1J4QjrgyHjLo3thmmBgQlI4AVtgkKhQABfTJ0SB4QwmcyWChuOy6ehZLB8aJsfI6XglYYwSLDWpglFMZhxXIFdTYiC4uIEnRlKzzOA4hmoJl0omQeRCQyrAAeME+KlKQko1ymqG2ewOEF5JEoO1uxgA1qRKpN+TggTZQCRBdg4JgYEhcPLUAB9JWqqqY9R0O16ZjzSqzEioKxUGiUQjU+SolgTe1tMQ7P5MnZWayfVASlZLPWzcRSVArR6yvA6IPZKC5fbkI7HannK6aW3qdNNcpq2rqIkOzN6MTrd0kE0-H1+phQBs6JDUMoPEo5jEU8tjbA44bHHSU1E4vFTmcV6mL2u1BsQADCKhgxiU6EL5FlU2wfK11kGVggADpbwqhsZSh64MQDSwbuRRfMduQppIfH4AQYNevb9jso4OvoBrlPMQJqmgcYfJQABuIwIHgEy+P42CBOgS7odO5Y3neko4ToIK5I467qH2zbSCUrAjm0XQ9J22AAKLGH4xhLre173jhhHlsUK5CSChLgno3K8qegqYMKcCiuKaBStcn6UN+PwykeeCUG+Vq6vqhrGrgVrwaO2a5KwpYQcuzTVuRmQ0WBg7QOSS4icMq5jsoE6iUuVK4viQnqOhk5idREC0QOtkER5EiFpALEQOxqE0NcQw0Ke5TGjszDuH+CWlCsfECY+ikaUochpkoCDKrgeaHCcRYSBMaTDOa6GXLxJEPuRlGRdFEYMeSzHdBAADqlAqlMoinueOpEaVpHGCFSbheRhJAA

πŸ’» Code

//
// Basic type definition //
//
type A =
// Base type A0 has ID and Title
  A0 &
  // Discriminated types(based on 'type' property) from A1 and A2
  (A1 | A2)

type A0 = {
  ID: string;
  Title: string; // <-- I added the "Title" as a measure to ensure that Omit<A,"ID"> won't be an 'any' empty object
}

//
// discrimination types //
//
type A1 = {
  type: "a1";
}

type A2 = {
  type: "a2";
  status: "status";
}

// This example shows that Omit is not working as expected
namespace not_working {
  //
  // Augmentation of "Type A" //
  // It just attempts to rename ID to be id
  //
  type B = Omit<A, "ID"> & {
    id: string;
  }

  //
  // Instance of Type B
  //
  const b: B = {
    Title: "",
    type: "a1",
    id: "",
  };

  // Clearly, it is expected that ...other satisfies A without its ID property.
  const {
    // Destructing to remove "id" property
    id,
    ...other
  } = b;

  const a: A = { // <-- TypeError
    ...other,
    ID: "",
  };
}

// This example shows that without omit it does work
namespace working {
  type B = A & {
    id: string;
  }

  const b: B = {
    ID: "",
    Title: "",
    type: "a1",
    id: "",
  };

  const {
    id,
    ID, // <-- Even when extract A's ID, so ...other should be like Omit<A, "ID" | "_id">
    ...other
  } = b;

  const a: A = { // <-- Works as expected
    ...other,
    ID: "",
  };
}

πŸ™ Actual behavior

I think that the Omit causes a conditional distributive type to trigger or something.

πŸ™‚ Expected behavior

I expect that the code example will work as expected and that the TypeError will not appear in the not_working namespace.

Additional information about the issue

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions