I'm trying to write some utility functions that clone objects, but change deep properties.
Here is an example of a somewhat useless version that just replaces a named property of an object with some other value which may be of a different type. The code works - it replaces the named property with the new value - but for some reason TypeScript can't figure out the type of the created object and gives a compile error. Why doesn't TypeScript like this and how can I make it work?
I could explicitly define the return type - but this gets awkward with versions of this function that change a property several levels deep.
it('change type of input object', () => {
const cloneWith = <T extends Record<string, unknown>, A extends keyof T, V>(
i: T,
a: A,
value: V
) => ({
...i,
[a]: value,
});
const source = { name: 'bob', age: 90 };
const result = cloneWith(source, 'age', 'old!');
// This test passes
expect(result.age).to.equal('old!');
// But compile error - number and string have no overlap -
// on this line
if (result.age === 'old!') {
console.log('That person is old!');
}
});