Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: How to type rest object destructure

If I have these two objects

interface Input {
    one?: string;
    two?: string;
    c?: string
}

interface Data {
    one?: string;
    a?: string;
    b?: string;
    c?: string
}

currently I have to do something like

const { one, two, ...restOfData } = input;
const data: Data = {...restOfData};

Is it possible to type ...restOfData directly?

I would like to be able to do this

const { one, two, ...data } = input;
data.one = 'test' + one;
data.a = one;
like image 641
joshhunt Avatar asked May 29 '18 21:05

joshhunt


People also ask

How do you Destructure an object in TypeScript?

And this is destructuring an object. Let's take the following example: const user = { firstname: 'Chris', lastname: 'Bongers', age: 32 }; const { firstname, age } = user; By using this destructuring, we extract specific properties from an object.

How do you Destructure a null object?

Use the logical OR operator to destructure from a nullable object in TypeScript, e.g. const { name, age } = obj || ({} as Person) . The logical OR operator is used to provide a fallback in case the object has a value of null or undefined .

What is the difference between Destructuring and spread Operator?

In summary: Destructuring assignment allows assigning the properties of an array or object to multiple variables at once. The syntax of the spread operator is three dots (…) followed by the object or an iterable (such as arrays). It expands the data structures, which can be used to make their shallow copies.


1 Answers

You can type the destructure as intersection of Input and a type which has all fields from Data but optional. For that "optional Data" type, you can use built-in Partial type:

const { one, two, ...data }: Input & Partial<Data> = input; 
// data type is  inferred as data: { c: string; a?: string; b?: string; }
// so you now can
data.a = one;

If you want some properties to remain in the data object, I can't think of anything better than doing two destructuring, one without "rest" object, and the second one with it. If you want one to remain in data, but remove two, you can do this

interface Input {
    one?: string;
    two?: string;
    c?: string
}

interface Data {
    one?: string;
    a?: string;
    b?: string;
    c?: string
}
let input: Input;

const { one } = input;
const { two, ...data }: Input & Data = input;

data.one = 'test' + one;
data.a = one;

If you want all properties to remain, you can have data as shallow copy of input like this

const { one, two } = input;
const { ...data }: Input & Data = input;
like image 148
artem Avatar answered Jun 18 '23 02:06

artem