13

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;
joshhunt
  • 5,197
  • 4
  • 37
  • 60

1 Answers1

13

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;
artem
  • 46,476
  • 8
  • 74
  • 78
  • Why is `Partial` necessary here, given all `Data` fields are optional already? – zerkms May 29 '18 at 23:33
  • @zerkms sorry in the process of updating the question to be more accurate. – joshhunt May 29 '18 at 23:35
  • That works pretty well but doesn't seem like it when I have to fields that are shared between the two objects. Will do some more digging to see if I can find a way around this – joshhunt May 29 '18 at 23:36
  • Ah it is because `one` is removed by the destructure therefore `...data` will not have a `one` field. Not sure how to get around this. – joshhunt May 29 '18 at 23:59
  • No idea how to do it in only one destructuring, but it can be done easily with two. I updated the answer. – artem May 30 '18 at 01:59
  • Hmm input will still have the `two` field in that case but `two` isn't available on `Data`. Will mark this as correct though as I don't think there is a better way at the moment. Thanks! – joshhunt May 30 '18 at 02:31