Open KiaraGrouwstra opened 7 years ago
Yeah this is kinda bummer! Is there any progress on this? Is it even possible to type in a way than you could change field types?
Btw how did you do workaround for this?
I'm not 100% sure if this is related issue, but it seems like the evolve typings don't handle optional parameters well. For example:
// with strict null checks
interface A {
foo?: string;
}
const x: A = {};
evolve(
{
foo: x => x.toUpperCase(),
},
x
// Error:(27, 5) TS2345: Argument of type 'A' is not assignable to parameter of type '{ foo: string; }'.
// Types of property 'foo' are incompatible.
// Type 'string | undefined' is not assignable to type 'string'.
// Type 'undefined' is not assignable to type 'string'.
);
I'd expect the foo method to be ignored if the property is missing (not undefined).
Unfortunately I need to move on right now, but would be interested in finding a solution for this.
Can we simply replace
export function $<T, U extends T>(transformations: Evolver<T>, object: U): U;
with
export function $<T, U>(transformations: Evolver<T>, object: U): U;
in evolve.d.ts
file?
@impankratov I think this would lose the constraint on U
that it should have the same set of keys?
I reckon the real problem is coming from the definition of Evolver<T>
:
export type Evolver<T> = Morphism<T, T> | { [K in keyof T]?: Evolver<T[K]> };
Specifically Morphism<T, T>
, which is saying that the type does not change.
minimum repro:
expected result: passes actual result: errors,
evolve
typing currently assumes input/output are similarPerfect inference here would be tough under current TS features (should need heterogeneous map), but it'd be nice if we could already allow this at least, even if inference ends up useless.