3

I encountered an error when trying to use Partial<T> in this scenario:

type WithName = {
    name: string
}

function test<T extends WithName>(x: T) {
    // Error: Type '{ name: "a"; }' is not assignable to type 'Partial<T>'.
    let a: Partial<T> = {
        name: 'a'
    }

    // Error: Type '{ name: "a"; }' is not assignable to type 'Partial<T>'.
    merge<T>(x, {name: 'a'})
}

declare function merge<T>(a: T, b: Partial<T>): T

Playground link

Is it a typescript limitation?

It works correctly with spread syntax: {...x, name: 'a'}, but I want to use a custom merge function.

dhmk083
  • 229
  • 2
  • 9
  • 1
    Ultimately it's because the caller chooses the type parameter and because properties can themselves be narrowed. So the caller can pass in a value of type `Larry` defined as `interface Larry {name: "Larry"}` and then `{name: "a"}` is absolutely not a `Partial`. See the linked q/a for more information. – jcalz Nov 01 '22 at 13:34
  • 1
    Thanks for the link! Btw, it turns out that the spread syntax form should also give the same error. – dhmk083 Nov 01 '22 at 14:14
  • It probably "should"... TypeScript interprets object spread on generics as being an intersection... e.g., if `x` is of generic type `X` then `{...x, a: 123}` is seen as being of type `X & {a: number}`, which is unsound when properties get overwritten. But if this were enforced properly, e.g., `Omit & {a: number}`, then a lot of real world code would break and it would introduce more problems than it would solve. For better or worse, a provably correct type system isn't one of the design goals of the language. – jcalz Nov 01 '22 at 14:57

0 Answers0