Open MistyKuu opened 7 years ago
You're right. Unfortunately this is a limitation of TypeScript that I don't see a way to work around in this circumstance. Unknown properties on object literals are not checked in the return value of functions which are given as arguments because TypeScript thinks its fine to accept a function which produces a return type which is a subtype of the desired type. A demo of this behavior:
interface HasX {
x: number;
}
function getHasX(): HasX {
// Extra properties are errors.
return { x: 1, y: 2 };
}
function callGetHasX(f: () => HasX) {
f();
}
// No error here.
callGetHasX(() => ({ x: 1, y: 2 }));
If this failure is enough of problem for you to not use this library, I understand. However, here are a few workarounds:
Use a variant of object spread from a library with a more restrictive signature.
In my code, I use pureAssign
from the pure-assign library instead of object spread or Object.assign
. Its signature of
function pureAssign<T>(baseObject: T, ...updates: Array<Partial<T>>): T
prevents unknown properties from being added which are not in the base type. Not to say you have to use this library in particular, but using a version of object assignment with more restrictive typing can be a generally good idea when writing TypeScript code.
Pull your handlers out into separate functions.
You can choose to write your code as
const reducer = reducerWithoutInitialState<Execute>()
.case(actions.calibrationSettingsDone, handleCalibrationSettingsDone);
const handleCalibrationSettingsDone =
(execute: Execute, payload: CalibrationSettingsDonePayload): Execute =>
({ ...execute, settings: payload.result });
Some people prefer this style anyways because it makes the reducer look less cluttered, although it does require more typing.
I'll think about this for a bit to see if I can come up with a better solution. If not, I'll make a note in the README about this.
Hey, I just tried to use the library but unfortunately there is no type check in .case method for return value.
If I implement my reducer like this:
it will not allow me to return settings1 property because it doesn't exist in Execute model and it's fine however in your library it's completely fine to return any object.