Skip to content

Commit 5154deb

Browse files
committed
feat: make update functions more ergonomic by adding overload that takes a state directly instead of currying
1 parent d53f02a commit 5154deb

File tree

5 files changed

+69
-27
lines changed

5 files changed

+69
-27
lines changed

example-app/ngrx-forms-0.1.0.tgz

5.02 KB
Binary file not shown.

example-app/package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example-app/src/app/app.reducer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ const itemFormReducer = groupUpdateReducer<ItemFormValue>({
1515
meta: (meta, itemForm) => updateGroup<MetaFormValue>({
1616
priority: priority => {
1717
if (itemForm.value.category === 'Private') {
18-
return setValue<number>(0)(disable(cast(priority)));
18+
return setValue(0, disable(priority));
1919
}
2020

21-
return priority.isEnabled ? priority : setValue<number>(1)(enable(cast(priority)));
21+
return priority.isEnabled ? priority : setValue(1, enable(priority));
2222
},
2323
})(cast(meta)),
2424
});

src/update-functions.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,15 @@ describe('update functions', () => {
114114
const resultState = setValue<FormGroupValue>({ inner: 'A' })(INITIAL_STATE);
115115
expect(resultState).not.toBe(cast(INITIAL_STATE));
116116
});
117+
118+
it('should call reducer for controls uncurried', () => {
119+
const resultState = setValue('A', INITIAL_STATE.controls.inner);
120+
expect(resultState).not.toBe(INITIAL_STATE.controls.inner);
121+
});
122+
123+
it('should throw if curried and no state', () => {
124+
expect(() => setValue<string>('')(undefined as any)).toThrowError();
125+
});
117126
});
118127

119128
describe(validate.name, () => {
@@ -128,6 +137,17 @@ describe('update functions', () => {
128137
const resultState = validate<FormGroupValue>(() => errors)(INITIAL_STATE);
129138
expect(resultState).not.toBe(cast(INITIAL_STATE));
130139
});
140+
141+
it('should call reducer for controls uncurried', () => {
142+
const errors = { required: true };
143+
const resultState = validate(() => errors, INITIAL_STATE.controls.inner);
144+
expect(resultState).not.toBe(INITIAL_STATE.controls.inner);
145+
});
146+
147+
it('should throw if curried and no state', () => {
148+
const errors = { required: true };
149+
expect(() => validate<string>(() => errors)(undefined as any)).toThrowError();
150+
});
131151
});
132152

133153
describe(enable.name, () => {

src/update-functions.ts

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -75,62 +75,84 @@ function abstractControlReducer<TValue>(state: AbstractControlState<TValue>, act
7575
return isGroupState(state) ? formGroupReducer(state as any, action) as any : formControlReducer(state as any, action);
7676
}
7777

78-
export function setValue<TValue extends FormControlValueTypes>(value: TValue): ProjectFn<FormControlState<TValue>>;
79-
export function setValue<TValue extends KeyValue>(value: TValue): ProjectFn<FormGroupState<TValue>>;
80-
export function setValue<TValue>(value: TValue) {
81-
return (state: AbstractControlState<TValue>) => abstractControlReducer(state, new SetValueAction(state.id, value));
78+
function ensureState<TValue>(state: AbstractControlState<TValue>) {
79+
if (!state) {
80+
throw new Error('state must not be undefined!');
81+
}
82+
83+
return state;
84+
}
85+
86+
// TODO: enable all overloads once conditional mapped types are implemented (https://github.com/Microsoft/TypeScript/issues/12424)
87+
88+
// export function setValue<TValue extends FormControlValueTypes>(value: TValue): ProjectFn<FormControlState<TValue>>;
89+
// export function setValue<TValue extends KeyValue>(value: TValue): ProjectFn<FormGroupState<TValue>>;
90+
export function setValue<TValue>(value: TValue): ProjectFn<AbstractControlState<TValue>>;
91+
export function setValue<TValue>(value: TValue, state: AbstractControlState<TValue>): AbstractControlState<TValue>;
92+
export function setValue<TValue>(value: TValue, state?: AbstractControlState<TValue>) {
93+
if (!!state) {
94+
return abstractControlReducer(state, new SetValueAction(state.id, value));
95+
}
96+
97+
return (s: AbstractControlState<TValue>) => setValue(value, ensureState(s));
8298
}
8399

84-
export function validate<TValue extends FormControlValueTypes>(validatorFn: (value: TValue) => ValidationErrors): ProjectFn<FormControlState<TValue>>;
85-
export function validate<TValue extends KeyValue>(validatorFn: (value: TValue) => ValidationErrors): ProjectFn<FormGroupState<TValue>>;
86-
export function validate<TValue>(validatorFn: (value: TValue) => ValidationErrors) {
87-
return (state: AbstractControlState<TValue>) => abstractControlReducer(state, new SetErrorsAction(state.id, validatorFn(state.value)));
100+
// export function validate<TValue extends FormControlValueTypes>(validatorFn: (value: TValue) => ValidationErrors): ProjectFn<FormControlState<TValue>>;
101+
// export function validate<TValue extends KeyValue>(validatorFn: (value: TValue) => ValidationErrors): ProjectFn<FormGroupState<TValue>>;
102+
export function validate<TValue>(validatorFn: (value: TValue) => ValidationErrors): ProjectFn<AbstractControlState<TValue>>;
103+
export function validate<TValue>(validatorFn: (value: TValue) => ValidationErrors, state: AbstractControlState<TValue>): AbstractControlState<TValue>;
104+
export function validate<TValue>(validatorFn: (value: TValue) => ValidationErrors, state?: AbstractControlState<TValue>) {
105+
if (!!state) {
106+
return abstractControlReducer(state, new SetErrorsAction(state.id, validatorFn(state.value)));
107+
}
108+
109+
return (s: AbstractControlState<TValue>) => validate(validatorFn, ensureState(s));
88110
}
89111

90-
export function enable<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
91-
export function enable<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
112+
// export function enable<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
113+
// export function enable<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
92114
export function enable<TValue>(state: AbstractControlState<TValue>) {
93115
return abstractControlReducer(state, new EnableAction(state.id));
94116
}
95117

96-
export function disable<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
97-
export function disable<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
118+
// export function disable<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
119+
// export function disable<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
98120
export function disable<TValue>(state: AbstractControlState<TValue>) {
99121
return abstractControlReducer(state, new DisableAction(state.id));
100122
}
101123

102-
export function markAsDirty<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
103-
export function markAsDirty<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
124+
// export function markAsDirty<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
125+
// export function markAsDirty<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
104126
export function markAsDirty<TValue>(state: AbstractControlState<TValue>) {
105127
return abstractControlReducer(state, new MarkAsDirtyAction(state.id));
106128
}
107129

108-
export function markAsPristine<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
109-
export function markAsPristine<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
130+
// export function markAsPristine<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
131+
// export function markAsPristine<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
110132
export function markAsPristine<TValue>(state: AbstractControlState<TValue>) {
111133
return abstractControlReducer(state, new MarkAsPristineAction(state.id));
112134
}
113135

114-
export function markAsTouched<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
115-
export function markAsTouched<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
136+
// export function markAsTouched<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
137+
// export function markAsTouched<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
116138
export function markAsTouched<TValue>(state: AbstractControlState<TValue>) {
117139
return abstractControlReducer(state, new MarkAsTouchedAction(state.id));
118140
}
119141

120-
export function markAsUntouched<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
121-
export function markAsUntouched<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
142+
// export function markAsUntouched<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
143+
// export function markAsUntouched<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
122144
export function markAsUntouched<TValue>(state: AbstractControlState<TValue>) {
123145
return abstractControlReducer(state, new MarkAsUntouchedAction(state.id));
124146
}
125147

126-
export function markAsSubmitted<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
127-
export function markAsSubmitted<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
148+
// export function markAsSubmitted<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
149+
// export function markAsSubmitted<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
128150
export function markAsSubmitted<TValue>(state: AbstractControlState<TValue>) {
129151
return abstractControlReducer(state, new MarkAsSubmittedAction(state.id));
130152
}
131153

132-
export function markAsUnsubmitted<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
133-
export function markAsUnsubmitted<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
154+
// export function markAsUnsubmitted<TValue extends FormControlValueTypes>(state: FormControlState<TValue>): FormControlState<TValue>;
155+
// export function markAsUnsubmitted<TValue extends KeyValue>(state: FormGroupState<TValue>): FormGroupState<TValue>;
134156
export function markAsUnsubmitted<TValue>(state: AbstractControlState<TValue>) {
135157
return abstractControlReducer(state, new MarkAsUnsubmittedAction(state.id));
136158
}

0 commit comments

Comments
 (0)