typed-typings / npm-ramda

TypeScript's type definitions for Ramda
MIT License
384 stars 64 forks source link

evolve typing disallows changing types #329

Open KiaraGrouwstra opened 7 years ago

KiaraGrouwstra commented 7 years ago

minimum repro:

R.evolve({ a: parseInt }, { a: '123' })

expected result: passes actual result: errors, evolve typing currently assumes input/output are similar

Perfect 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.

henrikra commented 6 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?

robations commented 6 years ago

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.

impankratov commented 5 years ago

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?

robations commented 5 years ago

@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.