Why are Typescript key/value types lost when used with spread operator in object literals

Viewed 339
const foo : {[key:string]:string} = {'hello': 'world', 'hi': 'there'};
const bar : number = 42
const foobar = {...foo, bar}
console.log(foobar)
// { hello: 'world', hi: 'there', bar: 42 }

The type of foobar resolves to {bar: number}. Why is this? I would expect the type of foobar to be {[key:string]: string|number} or {[key:string]: string} & {bar: number}


EDIT: I'm particularly confused on why in some cases the types are determined correctly:

const foo : {a: number} = {a: 1}
const bar : string = "bar"
const foobar = {...foo, bar}
console.log(foobar)
// foobar is type {bar: string, a: number}

Why does this case work, and the first case doesn't?

1 Answers

I think this is because construction with spread cannot handle 'property declaration priority' properly. (indexed type properties have lower priority declaration). I think it can be improved in future versions. Try this:

const foobar = { ...foo, bar } as (typeof foo & { bar: typeof bar});
Related