Skip to content

DeepPartial typing does not play nicely with branded types #4235

@flakey-bit

Description

@flakey-bit

Prior Issues

What is the current behavior?

Assume some simple branded type, for example

type Money = string & { __brand: "Money" };

Assume some type, e.g. Transaction that makes use of the branded type in a property, for example

export interface Transaction {
  amount: Money;
  postedDateTime: string;
}

For a given type T, and an instance variable declared as of type DeepPartial<T>, an instance of T should be assignable to the instance variable of type DeepPartial<T>, but with the current implementation this is violated.

The problem is an overly simplisitic DeepPartial definition, there are better implementations out there. NB: I believe the implementation prior to #3369 did not have this problem (but obviously that PR addressed other issues).

Steps to Reproduce

// Money is a "branded" string
type Money = string & { __brand: "Money" };

export interface Transaction {
  amount: Money;
  postedDateTime: string;
}

let foo: DeepPartial<Transaction> = {
  postedDateTime: "2019-11-01"
};

const bar: Transaction = {
  amount: "300.50" as Money,
  postedDateTime: "2019-11-02"
};

foo = bar; // barfs with compile error

The error:

Error:(29, 1) TS2322: Type 'Transaction' is not assignable to type 'DeepPartial<Transaction>'.
  Types of property 'amount' are incompatible.
    Type 'Money' is not assignable to type 'undefined'.

What is the expected behavior?

An instance of T is assignable to a variable of type DeepPartial<T>, even if T includes properties that are branded strings / branded numbers.

Environment Details

Redux 4.1.2
TypeScript 4.5.2

Unsure as to whether it worked with previous versions of Redux.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions