Search code examples
typescript

TS2322: Type is assignable to constraint of type V, but V could be instantiated with a different subtype of constraint


I have the following typescript function

export const f1 = <V extends Record<string, any> & { name: string }>(vars: Omit<V, 'name'>, name: string): V => {
    const v: V = {...vars, name}
    return v
};

which gives the error

TS2322: Type  Omit<V, "name"> & { name: string; }  is not assignable to type  V 
 Omit<V, "name"> & { name: string; }  is assignable to the constraint of type  V ,
  but  V  could be instantiated with a different subtype of constraint  Record<string, any> & { name: string; }

I do not see how that can be the case here.


Solution

  • It's not that intuitive but I think easy way to look at it is that the function should also work if you are to specify the generic explicitly f1<{}>(...).

    So if you have type T1 that fulfils extends Record<string, any> & { name: string }

    type T1 = {
      name: number;
      other: "stuff";
    } & {
      name: string;
    };
    

    This more less resolves as

    {
        name: never;
        other: "stuff";
    }
    

    Then Omit<T1, "name"> type is

    {
        other: "stuff";
    }
    

    If you call f1 like

    f1<T1>({ other: "stuff" }, "name");
    

    Then when you have { ...vars, name} you get

    {
        other: "stuff";
        name: string;
    }
    

    which does match specified generic

    {
        name: never;
        other: "stuff";
    }
    

    Same example starting with a different type like

    type T1 = {
      name: "some specific string";
      other: "stuff";
    } & {
      name: string;
    };
    

    shows the same thing but maybe example is more realistic.