ts-belt icon indicating copy to clipboard operation
ts-belt copied to clipboard

The typing of `D.update` / `D.updateUnsafe`

Open ssnielsen opened this issue 2 years ago • 3 comments

I came across a use-case of D.update and D.updateUnsafe that gave me a bit of trouble wrt. its typing.

Example (granted, a bit contrived):

// If I have an object of this shape
const myObject = {
	name: string;
};

// And then use D.update / D.updateUnsafe to change name
const myChangedObject = D.updateUnsafe('name', object => object.name.split(''));

Intuitively, I'd expect the type of myChangedObject.name to be string[], but in practice, it becomes string & string[] (i.e. the original type of name is combined with the return type of the updater function).

Looking at the typings of D.update and D.updateUnsafe, the result of my example definitely makes sense, but I'm wondering a bit why the typings includes the original type of the updated property to begin with 🤔

Happy to hear your takes on this!

ssnielsen avatar Mar 03 '23 11:03 ssnielsen

could be fixed easily by changing the signature of the update function with

export declare function update<T, K extends keyof T, R>(dict: T, key: K, fn: (value: T[K]) => R): {[Kx in Exclude<keyof T,K>]:T[Kx]} & {[Kx in K]:R} & {};

here's the result in my local environment image

the output type could be optimized, by removing & with export type Simplify<T> = {[KeyType in keyof T]: T[KeyType]} & {}; for better readability.

JUSTIVE avatar Jan 22 '24 04:01 JUSTIVE

btw, unlike other fp languages, typescript can infer keyof T type in compile-time, so the value of T[K] should be typeof T[K] instead of Option<T[K]>, I guess.

JUSTIVE avatar Jan 22 '24 04:01 JUSTIVE

revisited this issue, seems D.update has been fixed in 4.0.0, but updateUnsafe isn't.

JUSTIVE avatar Mar 11 '24 08:03 JUSTIVE