Closed Gaelan closed 7 years ago
I brought this up recently with @mhegazy, and it can really come in handy, especially
interface Props { /*...*/ };
class Foo implements Props {
constructor(opts: partial Props) { /*...*/}
}
let NewThing: NewMembers & (partial ThingImMixingInWith) = { /*completionHere*/
And I'm sure in other scenarios. How we choose to go about making this available is a separate matter.
Just for bookkeeping, it's the same as $Shape from https://github.com/Microsoft/TypeScript/issues/2710.
@s-panferov Does $Shape
match deepPartial
or partial
? (deepPartial
is recursive for sub-objects)
When you want completion from members you're going to mix in but you don't want to implement all the required members.
And type guard against anything that isn't actually in the interface.
I would suspect $Shape
could match partial
at the least if not deepPartial
(e.g. a non-strict object literal check).
Why wouldn't the behaviour always just be like deepPartial
... If you are already in the mode of not being strict, why would you ever suddenly not want that to be deep?
@kitsonk I was thinking of React.setState
, or any other function that overwrites keys of one object with keys from another, not recursing.
This would work nicely:
type foo = {a?:string, b?:string};
type fooStrict = foo & any!optional; // {a: string, b: string}
type fooOptional = foo & any!strict; // {a?: string, b?: string}
This would make typings for lodash/underscore pretty awesome.
Would also be usefull in cases where you get a partial model as a param on the constructor to build the actual model. This way we wouldn't need to create a sibling interface just to hold the same properties with different optionality.
class Person {
name: string;
surname: string;
birthday: Date;
numberOfThings: number;
constructor(initialValues: partial Person) {
this.name = initialValues.name;
this.surname = initialValues.surname;
this.birthday = initialValues.birthday;
this.numberOfThings = initialValues.numberOfThings;
}
}
new Person({name: 'Fred', surname: 'Galvão', numberOfThings: 2});
Yes, this would be extremely handy! Another good use case is React "higher-order" components - I want to implement a component that acts just like another, "lower-order" component, except it automatically calculates the value of some of its props... example time:
interface IUserAvatarProps {
url: string,
size?: number
}
class UserAvatar extends React.Component<IUserAvatarProps, {}> {
//...
}
interface ISmartUserAvatarProps implements partial IUserAvatarProps {
userId: string
}
class SmartUserAvatar extends React.Component<ISmartUserAvatarProps, {avatarUrl: string}> {
render() {
return <UserAvatar url={this.state.avatarUrl} {...this.props} />;
}
componentWillMount() {
// Fetch this.state.avatarUrl from this.props.userId
}
}
// Later...
<SmartUserAvatar id="1234" size={32} />
Yet another use case would be backbone models which have defaults and the constructor takes a partial set of attributes which override the defaults:
interface CarData { make: string, model: string }
class Car extends Backbone.Model<CarData> {
defaults: CarData = {
make: 'BMW',
model: '7'
}
}
new Car({ model: 'X5' });
@DomBlack just pointed me to this. Thanks! Just for backward/forward reference, this was also discussed in #392.
+1
+1
For me, the big benefit of such functionality would be in being able to create typesafe APIs around the various libraries for immutable data structures like updeep
or immutable.js
. In both of these libraries, the efficiency of the library hinges on being able to modify data structures by passing in the "deltas" you wish to apply. And the fundamental issue with type safety is a way of expressing the types of these deltas in the context of a parametric type for the complete data.
Of course, some basic language level functionality for implementing or expressing lenses would also be a potential way of addressing the issue.
There is a use case for the Object.assign
(from ES6).
It could be defined using partial types like this:
function assign<T>(target: subset of T, ...sources: (subset of T)[]): T;
Now I could do this:
var x = Object.assign({name:"Miguel Angelo"}, {age:32});
As all arguments are stated to be subsets of T, the call expression type could be inferred to be:
interface __anonymous {
name: string;
age: number;
}
That would be assignable to the following type:
interface IPerson {
name: string;
age?: number;
}
It'd be assignable because __anonymous
is a super set of IPerson
.
If this was possible, I could pass a variable y
of type IPerson
to the assign method. The following pattern is useful when changing an immutable object:
var x = Object.assign({}, y, {name:"Miguel Angelo"});
As y
is not known to have age or not, the resulting inferred type would have an optional age
, resulting in a type that is equal to the type IPerson
itself. The inference process could see that, and infer that this call expression type really is IPerson
.
The final case, would be when I state the type of T when calling. The inference algorithm could then make sure that the resulting type is what I expect, or give me an error:
var x = Object.assign<IPerson>({name:"Miguel"}, {age:32}); // the combined subsets is a valid IPerson
var x = Object.assign<IPerson>({}, {name: "Miguel"}); // the combined subsets is a valid IPerson
var x = Object.assign<ILawyer>(new Lawyer(), new Person()); // the combined subsets is a valid ILawyer
var x = Object.assign<IPerson>({}, {age: 30}); // ERROR: the combined subsets is a valid Person
For the keyword, it could be partial
, subset of
, or anything, but I propose it to be subset of
, because then there could be a superset of
. But then partial
could have a complete
counterpart... I don't know... anything is good enough.
Does this make sense?
Sorry @masbicudo if I didn't understand your example correctly but I think it can already be typed using "type parameters as constraints", see the first post in https://github.com/Microsoft/TypeScript/pull/5949
I've done this as a test, and I am pretty excited with the possibilities this seems to open.
interface xpta
{ a : number
, b : string
, c : number[]
}
interface xptb
{ a : number
, b : string
}
function assertSubType<T extends U, U>(x: T, y: U):void { };
assertSubType(<xpta>null,{a: 6, b:'aa'}); /* compiles, does nothing as expected */
assertSubType(<xpta>null,{a: 6, d:4}); /* gives error in typescript */
assertSubType(<xpta>null,{a: 6, c:'aa'}); /* gives error in typescript */
Is it related?
With the latest 1.8-beta, it's possible to get this to work when both type parameters are defined on the function. Unfortunately, I doesn't seem to solve the React.Component.setState
use case as it is using generic type classes.
I.e.:
declare function setState<T, S extends T>(state: S, partial_state: T) // works!
interface Component<S> {
state: S
setState<T, S extends T>(partial_state: T) // doesn't work as S is considered a new type param
}
I have the same issue as @guncha when trying to type a cursor structure
interface Cursor<T> {
get(): T,
set(data: T)
merge<T extends U, U>(val: U)
}
+1
Agree with @masbicudo about Object.assign()
use case +1
@mjohnsonengr since TypeScript 1.8 Object.assign
has a nice type definition :rose:
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a
* target object. Returns the target object.
* @param target The target object to copy to.
* @param source The source object from which to copy properties.
*/
assign<T, U>(target: T, source: U): T & U;
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a
* target object. Returns the target object.
* @param target The target object to copy to.
* @param source1 The first source object from which to copy properties.
* @param source2 The second source object from which to copy properties.
*/
assign<T, U, V>(target: T, source1: U, source2: V): T & U & V;
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a
* target object. Returns the target object.
* @param target The target object to copy to.
* @param source1 The first source object from which to copy properties.
* @param source2 The second source object from which to copy properties.
* @param source3 The third source object from which to copy properties.
*/
assign<T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a
* target object. Returns the target object.
* @param target The target object to copy to.
* @param sources One or more source objects from which to copy properties
*/
assign(target: any, ...sources: any[]): any;
I might have read your question wrong. Just thought I'd try to be helpful still :rose:
@basarat that works except I would still have to define each partial interface as in the below example. I suppose it's just a convenience factor, but it would be nice if I didn't have to define PersonName to get typing information on the name in the second arbitrary object. Having the second interface just seems like a nightmare to maintain.
interface Person {
name: string;
age: number;
}
interface PersonName {
name: string;
}
var person = { name: "asdf", age: 100 };
Object.assign<Person, PersonName>({}, person, { name: "mjohnsonengr" })
I guess a possible shortcut is
var updatePersonName = (person: Person, name: string) => Object.assign({}, person, { name });
@mjohnsonengr I blindly copy pasted from lib.d.ts
without actually looking at it. I should have linked to : https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#type-parameters-as-constraints :rose:
function assign<T extends U, U>(target: T, source: U): T {
for (let id in source) {
target[id] = source[id];
}
return target;
}
let x = { a: 1, b: 2, c: 3, d: 4 };
assign(x, { b: 10, d: 20 });
assign(x, { e: 0 }); // Error
@basarat Ohh! Now that's fancy! I'll have to play with that. Thanks for pointing that out to me!!
One question, given this modified example from (my own example) above:
interface A
{ a : number
, b : string }
interface O // optional additional field
{ a : number
, o? : string };
interface M // mandatory additional field
{ a: number
, m: string };
function assertSubType<T extends U, U>(x: T, y: U):void { };
assertSubType(<A>null,<M>null); // gives error as expected
assertSubType(<A>null,<O>null); // does not give an error
So, my question is, is an object with an optional field not included on the 'extended object' a valid subtype?
@basarat this good But we need Somthing like this
class MyGenericClass<S>{
setState<U => S extends U >(state: U, callback?: ()=>void): void
}
var myInstance = new MyGenericClass<{a: string; b: number; c: Array<string>}>();
myInstance.setState({a: 'any value'}); // ok
myInstance.setState({a: 'any value', c: []}); // ok
myInstance.setState({a: 'any value', c: [2,3,4]}); // error
myInstance.setState({a: 'any value', b: 'any not number val'}); // error
In this example we added condition for U type
What do you think about it?
@basarat
//like assign
class MyGenericClass<S>{
setState<U, S extends U >(state: U, callback?: ()=>void): void
}
but now S not reffers to Generic param of class
how about adding java's super
keyword?
class MyGenericClass<S>{
setState<U super S >(state: U, callback?: ()=>void): void
}
This looks to me like a particular application for some more generalized concept of a compile-time type transformation function. I'm not sure if the "partial type" naming successfully captures what it actually does (I would expect a "partial" type to be simply a type that is declared across multiple files as in C#).
I think a more appropriate name for these transformations may be something like optionalize
and deepOptionalize
respectively (there may be a better name but that's the most reasonable one I found so far).
So for this interface:
interface MyInterface {
prop: number;
optionalProp?: string;
obj: SomeOtherInterface;
}
The transform could be applied as a (built-in) compile-time function, which would accept a type and returns a type, and would only work at type positions, e.g:
type WeakenedMyInterface = optionalize(MyInterface);
type DeeplyWeakenedMyInterface = deepOptionalize(MyInterface);
let x: optionalize(MyInterface);
function func(arg: deepOptionalize(MyInterface)) {
...
}
("Optionalize" seems to be a valid English word meaning "to make optional" according to the Oxford Dictionary)
@malibuzios what about generics? is that what you're proposing?
class MyGenericClass<S>{
setState(state: Optionalize(S), callback?: ()=>void): void
}
@amir-arad
I believe it is too early to call this a 'proposal' but I think this notation could also work with generic parameters as well. I changed the casing to optionalize
to reflect the more common convention for functions though (so it doesn't get confused with a type).
There will be types that are not really applicable here like null
, undefined
, number
, string
etc. so it may (or may not depending on what works best) require a generic constraint like:
class MyGenericClass<S extends object>{
setState(state: optionalize(S), callback?: ()=>void): void
}
(by object
here I meant the type proposed in #1809, which isn't implemented yet)
The idea of type functions reminds me of Flow's experimental (and almost completely undocumented) $Keys<>
, $Subtype<>
, $Diff<>
, etc. types.
If we're going that far... it might be worth considering the other use case which would benefit from compile-time post-processing of types: ImmutableJS (and similar libraries).
It would be really nice to define something like let foo: ImmutableRecord<{x: string}>
and have foo.set('x', 'bar')
automatically typechecked as a string. Not sure exactly what this would look like in practice or in the type definitions, though.
@dallonf
The syntax I've suggested was only meant to create the 'analogy' or 'sense' of a function. It is not actually a user-definable function but a built-in language construct with function-like syntax.
I felt that having function-like syntax would demonstrate the semantics here better - which is the application of a transformation to an interface type. Additionally this opens some space to further syntax that may be added in the future of this kind (e.g. doSomething(MyType)
, doSomethingElse(MyType)
.
@malibuzios
We've open sourced Tspoon, our Typescript AST visitors engine. We use it to manipulate Typescript's semantics.
Want to use it to try and implement optionalize
? I'd be glad to show you the ropes.
@amir-arad
Interesting, I'll take look at it when I have time, though I'm not that familiar with the compiler internals and API (I guess at some point it would seem reasonable for me to learn, though).
Actually I recently noticed there are other relatively simple type transformations I found to be useful and important for me right now (and may be for others) :
I've considered writing an experimental proposal for user-defined compile-time type transformations.. (at least to exchange some ideas, not necessarily to have it implemented any time soon - I understand it could be problematic for many reasons, see more below)
I even considered a syntax (for illustration purposes only!) inspired by the type alias syntax, something like:
// Returns the same type where all properties are made optional
type optionalize(typeMetadata: TypeMetadata): TypeMetadata {
for (let propertyName in typeMetadata.properties)
typeMetadata.properties[propertyName].isOptional = true;
return typeMetadata;
}
// Returns the same type where all properties are made optional, recursive
type deepOptionalize(typeMetadata: TypeMetadata): TypeMetadata {
for (let propertyName in typeMetadata.properties) {
let currentPropertyMetadata = typeMetadata.properties[propertyName];
currentPropertyMetadata.isOptional = true;
if (currentPropertyMetadata.isObject)
deepOptionalize(currentPropertyMetadata)
}
return typeMetadata;
}
The results of this could be somehow cached, so compilation performance is not necessarily a problem. Executing at compile time wouldn't be as well (the compiler is running in Javascript VM after all). Error reporting shouldn't also be a problem, I believe.
The "real" potential problems would be what would the compiler do to avoid and detect infinite execution, stack overflows, large memory consumption etc. It could also be that the scope of this would simply appear too narrow and something closer to AST transforms would seem to be more widely useful.
Another use case: React's getDefaultProps()
or Component.defaultProps
. These properties are of the type subset of Props
.
React's default props are actually an even more complex case than that - the external facing props type is mixed with it! Err, that doesn't make any sense to describe it, lemme write some code:
interface Props {
x: string;
y?: string;
}
class MyComponent extends React.Component<Props, {}> {
// Fulfills a required property!
static defaultProps = {
x: "foo"
};
render() { /* this.props will be of type Props */ }
}
// Later...
ReactDOM.render(<MyComponent />, document.getElementById('app'));
That last line should be perfectly legal, because its defaultProps
fulfills the requirement of x
. In other words, outside of the component, its props type is {x?: string, y?: string}
.
Not sure if that's relevant to the current discussion but I thought it was worth bringing up.
Another potential use case here, although I think everyone is really on the same page. I think that the constructor options example @DanielRosenwasser gave will be the most beneficial.
Here's the default lib.es6.d.ts
interface for CSSStyleDeclaration:
interface CSSStyleDeclaration {
alignContent: string;
alignItems: string;
alignSelf: string;
alignmentBaseline: string;
animation: string;
animationDelay: string;
animationDirection: string;
animationDuration: string;
animationFillMode: string;
animationIterationCount: string;
etc: string;
getPropertyPriority(propertyName: string): string;
[index: number]: string;
}
It would be nice to be able to use that object for setting inline style objects, without having to apply it fully.
And, this is sprawling a little (or a lot), but what do you think about the ability to remove props from a partial extend as well? Too much?
interface StyleObject partial CSSStyleDeclaration {
-getPropertyPriority;
}
const x: StyleObject = { // valid partial match
alignContent: 'center',
animationDelay: '1s'
};
const y: StyleObject = { // invalid, because getPropertyPriority is removed from StyleObject
getPropertyPriority: (input: string) => {
console.log(string);
return string;
}
};
I have a use case for partial types: I'm working on a vdom library that allows partially applied nodes. I would literally need dependent types (or at least C++-style variadic types with specializations) to correctly type this case, but for practical reasons, I'd gladly accept partial types to ease the problem.
// This is completely wrong and too permissive for partially applied partial nodes.
type Base<T, U> = ComponentFactory<T, U> | PartialNode<T, U, any>;
// Supertype for component factories
interface ComponentFactory<T, U> {
// Merge partially applied properties.
merge?(initial: T, rest: T): void;
}
interface PartialNode<T, U, V> {
mask: nodes;
type: Base<T, U & V>;
attrs: U;
}
export function part<T, U, V>(type: Base<T, U>, attrs?: U): PartialNode<T, U, V>;
// I'd be okay with this:
type Base<T, U> = ComponentFactory<T, U> | PartialNode<T, U>;
// Supertype for component factories
interface ComponentFactory<T, U> {
// Merge partially applied properties.
merge?(initial: partial T, rest: partial T): void;
}
interface PartialNode<T, U> {
mask: nodes;
type: Base<T, U>;
attrs: partial U;
}
export function part<T, U>(type: Base<T, U>, attrs?: U): PartialNode<T, U>;
Type subtraction could be a useful feature, I've seen it required in a few places, mostly library functions. It will also be needed for ES7 type destructuring:
let {a, b, ...rest} = this.props
// type of rest here?
As for the syntax, I'd like to see something like type C = A - B
which is
more general than removing single properties.
@guncha That includes React and Object.assign
now, where React already uses spread attributes. And yes, type subtraction would be more general, but it's also a bit harder to implement. It is effectively the inverse of intersection, if my memory of set theory is correct.
I think partial of something has also hidden meaning: it must have at least one property implemented.
E.g. currently this is not an error, and a painful:
let a = "test";
let b: {
hello?: string;
what?: string;
}
b = a; // not an error, because {} is compatible with string
But consider this with partial:
let a = "test";
let b: {
hello: string;
what: string;
}
let c: partial typeof b
c = a; // this could be error!
Because partial could also mean that at least one of the properties are implemented, and "test" does not implement hello or what.
Then {} should not be compatible with any of the partial types.
@Ciantic
It's surprising to me that string
is assignable to {}
, that seems strange.
I would like it if {}
was compatible with partial types because I'd like to be able to "build up" an object after instantiating it. E.g.
interface IFoo { foo: string; }
const foo: partial IFoo = {}; // foo does not yet implement IFoo, but will eventually
foo.foo = 'foo';
// maybe someday static analysis could determine that foo must fully implement IFoo at this point
Edit: Maybe {}
is OK as a partial if explicitly cast (i.e. {} as partial IFoo
).
How about this?
interface IFoo { foo: string; }
let foo: partial IFoo;
let bar: IFoo;
foo = {}; // not ok, {} does not implement any members of IFoo
foo = {} as partial IFoo; // ok, explicit cast
bar = foo; // not ok, partial IFoo does not implement IFoo
bar = foo as IFoo; // ok, explicit cast (maybe a warning?)
foo.foo = 'foo';
bar = foo; // ok, static analysis shows foo implements IFoo now
there seems to be a lot of good things going on in this thread! 🌷
Here is another use case relate to option bag:
interface Bag {
requireA: string;
optionalB?: string,
}
class Base {
constructor(options: Bag) { ... }
}
class Child extends Base {
constructor(options: partial Bag) {
options.requireA = options.requireA || 'child default value';
super(options);
}
}
...or if there is a better way to do this. 🌹
as a few people noticed, what you need isn't a partial types but a subtraction operation on types: V = T - U
speaking of which: https://github.com/Microsoft/TypeScript/issues/4183
@aleksey-bykov Thanks for the pointer!
@aleksey-bykov That will partially fix my particular case. What I need is the set difference between two object types, but with P
below constrained to a partial subtype of A at minimum.
interface PartialNode<T, P, A> extends Base<T, A - P> {
mask: nodes;
type: Base<T, A>;
attrs: P;
}
// Something like this, where P partially extends A
export function part<T, P extends partial A, A>(
type: Base<P, A>,
attrs?: P
): PartialNode<T, P, A>;
My case will also be difficult to infer, which is part of why I mentioned earlier that dependent types are probably the easiest thing to work with and while still keeping the types inferrable.
Running into the lack of partial typing more and more often. Would love to see a solution here.
This pattern is used a lot in Redux, where you have some object of type A
that you want to clone and update properties on, e.g.
interface PartialState {
foo?: string
}
interface State {
foo: string
}
function update(patch: PartialState): State { return Object.assign({}, state, patch); }
const state = { foo: 'baz' };
const newState = update({ foo: 'bar' }, state);
Let me know if I'm talking nonsense, but as far as I understand
function exampleCovariant<Subtype extends Supertype>(arg: Subtype) { … }
is basically type parameter covariance — we expect Subtype
to be… well, a subtype of Supertype
, is that correct?
Then, wouldn't the requirement in question be solved by adding ability to specify contravariance constraints to type parameters, like so (syntax borrowed from Java, could be probably bikeshedded):
function exampleContravariant<Supertype super Subtype>(arg: Supertype) { … }
in which case the arg
would be expected to be any appropriate supertype of Subtype
. And since as far as I understand TypeScript's type system is structural, it would mean syntax and semantics of super
constraint would admit code like so:
class Component<State>
{
private _state: State;
get state() { return this._state; }
protected setState<NewState super State>(newState: NewState)
{
this._state = { ..._this.state, ...newState };
}
}
interface CounterState
{
count: number;
interval: number;
}
class Counter extends Component<CounterState>
{
private setIntervalHandle: any;
get count() { return this.state.count; }
constructor<StateSubset super CounterState>(initialState: StateSubset)
{
this.setState({count: 0, interval: 500, ...initialState});
// calling `this.state({top: "kek"})` would've been illegal here since
// it's not a supertype of `CounterState` and would produce
// a compile-time error
}
start()
{
this.setIntervalHandle =
setTimeout(() =>
this.setState({count: this.state.count + 1})),
this.state.interval;
}
stop()
{
clearTimeout(this.setIntervalHandle);
this.setIntervalHandle = null;
}
}
which as far as I understand was one of the motivating examples for this proposal.
Why I think it's better than partial
? Simple consistency and symmetry — if generics admit covariance bounds and contravariance seems to solve this problem, why not admit contravariance bounds as well. That said this alone would not be able to type Object.assign
for example, it would require variadic generics as well (which might be perceived as a downside, but to me variance + variadic generics seems like the proper solution).
Is there any downside I'm missing here? Maybe it's harder to infer than partial-ness?
That sounds acceptable to me, as long as it remains clear it's not a solution to #1394 (this is method variance, not type variance).
On Thu, Sep 8, 2016, 03:17 Tomek Mańko notifications@github.com wrote:
Let me know if I'm talking nonsense, but as far as I understand
function exampleCovariant
(arg: Subtype) { … } is basically type parameter covariance — we expect Subtype to be… well, a subtype of Supertype, is that correct?
Then, wouldn't the requirement in question be solved by adding ability to specify contravariance constraints to type parameters, like so (syntax borrowed from Java, could be probably bikeshedded):
function exampleContravariant
(arg: Supertype) { … } in which case the arg would be expected to be any appropriate supertype of Subtype. And since as far as I understand TypeScript's type system is structural, it would mean syntax and semantics of super constraint would admit code like so:
class Component
{ private _state: State; get state() { return this._state; } protected setState<NewState super State>(newState: NewState) { this._state = { ..._this.state, ...newState }; }
} interface CounterState { count: number; interval: number; } class Counter extends Component
{ private setIntervalHandle: any; get count() { return this.state.count; } constructor<StateSubset super CounterState>(initialState: StateSubset) { this.setState({count: 0, interval: 500, ...initialState}); // calling `this.state({top: "kek"})` would've been illegal here since // it's not a supertype of `CounterState` and would produce // a compile-time error } start() { this.setIntervalHandle = setTimeout(() => this.setState({count: this.state.count + 1})), this.state.interval; } stop() { clearTimeout(this.setIntervalHandle); this.setIntervalHandle = null; }
}
which as far as I understand was one of the motivating examples for this proposal.
Why I think it's better than partial? Simple consistency and symmetry — if generics admit covariance bounds and contravariance seems to solve this problem, why not admit contravariance bounds as well. That said this alone would not be able to type Object.assign for example, it would require variadic generics as well (which might be perceived as a downside, but to me variance + variadic generics seems like the proper solution).
Is there any downside I'm missing here? Maybe it's harder to infer than partial-ness?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Microsoft/TypeScript/issues/4889#issuecomment-245513912, or mute the thread https://github.com/notifications/unsubscribe-auth/AERrBH7wdYO_EmS5-7i0391pjPkoXtaBks5qn7aAgaJpZM4GAkXw .
Potential Use Cases
deepPartial
)React.setState
(partial
)