'How to use <Omit> and generic types in typescript?

I am trying to generalise a service layer in an API in typescript using a base Data Transfer Object.

To not have to re-write the types definition i'm using <Omit>. However, it raises some typescript errors that i am not able to understand.

For instance, i do not understand why the following code:

type A = { a: string };
function test<T extends A>(ot: Omit<T, "a">): T {
  return {
    ...ot,
    a: "a",
  };
}

is raising the following error:

Type 'Pick<T, Exclude<keyof T, "a">> & { a: string; }' is not assignable to type 'T'. 'Pick<T, Exclude<keyof T, "a">> & { a: string; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'A'.

I understand why

function test<T extends string>():T {return "This is not specific enough!"}

does not work, but in the case above we are just defining dynamically the omitted field, we are not forgetting any constraint. What am i getting wrong?



Solution 1:[1]

Your function fails type-checking because it is not type-safe. The error message explains: your function returns something which "is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'A'."

For example, type Foo = {a: 'foo'} is also a sub-type of the constraint A. If your function is called like test<Foo>(obj), then it promises to return something of type Foo, but the actual return value is not assignable to the type Foo.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 kaya3