Partial Types

This is a proposal for #4889 and a variety of other issues.

Use Cases

Many libraries, notably React, have a method which takes an object and updates corresponding fields on some other object on a per-key basis. It looks like this

function setState<T>(target: T, settings: ??T??) {
  // ...
}
let obj = { a: 2, b: "ok", c: [1] };
setState(obj, { a: 4 }); // Desired OK
setState(obj, { a: "nope"}); // Desired error
setState(obj, { b: "OK", c: [] }); // Desired OK
setState(obj, { a: 1, d: 100 }); // Desired error
setState(obj, window); // Desired error

Observations

  • The update is rarely recursive (an exception is Mongo's query); this is a "shallow" operation
  • It's not desirable to allow "new" properties to appear
  • We're not looking for a supertype of some type (due to the non-recursive nature)

Unary partial T operator

A type partial T behaves as follows:

  1. Its properties are the same as the properties of T, except that those properties are now optional
  2. A S type is only assignable to type partial T if S has at least one property in common with T
    • Otherwise regular structural subtype/assignability rules apply
  3. The type partial (T | U) is equivalent to (partial T) | (partial U)
  4. The type partial (T & U) does not expand (this would interact poorly with rule 2)
  5. Any type T is always a subtype of partial T
  6. The type partial T is equivalent to T if T is any, never, null, or undefined

More thoughts to come later, likely