I want to use destructoring to create a new object from an existing one.
In JS i do the following:
const objOrig = { a: 1, b:2, c: 3};
const objChanged = { ...({a, c} = objOrig), ...{b:'S'} };
// => objChanged is: { a: 1, b: 'S', c: 3 }
If I want to do the same with TS I get: TS18004: No value exists in scope for the shorthand property 'a'. Either declare one or provide an initializer.
type S = {a: number; b: number| string; c: number};
const objOrig: S = { a: 1, b: 2, c: 3};
const objChanged: S = { ...({a, c} = objOrig), ...{b:'S'} }
If TS is realy a superset of JS, then it should be possible, so: what am i doing wrong?
CodePudding user response:
The problem with your JS code is that it's actually declaring two global variables, a
and c
:
const objOrig = { a: 1, b:2, c: 3};
const objChanged = { ...({a, c} = objOrig), ...{b:'S'} };
console.log(a, c);
console.log(objChanged);
Turn on strict mode and see that it fails in JavaScript:
"use strict";
const objOrig = { a: 1, b:2, c: 3};
const objChanged = { ...({a, c} = objOrig), ...{b:'S'} };
The correct way to change the object is this:
const objChanged: S = { ...objOrig, ...{ b:'S' } }
but since there is only one property being changed, you can simplify to:
const objChanged: S = { ...objOrig, b:'S' }
CodePudding user response:
As vera said, the JS code is easy to misunderstand.
Perhaps I have kept the example too simple. The objChanged should also be a different TS type.
I was able to solve my problem as follows.
// TS-code
type S1 = { a: number; b: number; c: number };
type S2 = { a: number; b: string; c: number };
const origObj: S1 = { a: 1, b: 2, c: 3 };
let a: S1['a'];
let c: S1['c'];
const otherObj: S2 = { ...(({ a, c } = origObj), { a, c }), ...{ b: 'S2' } };
console.log(`origObj: ${JSON.stringify(origObj)}\notherObj: ${JSON.stringify(otherObj)}`);
Thanks again for the replies.