Skip to content

Object spread drops index signature #27273

Open
@ajafff

Description

@ajafff

TypeScript Version: 3.0.1

Search Terms:
spread index signature, spread indexer

Code

declare var v: Record<string, string>;

let v2 = {...v}; // works
let v3 = {a: '', ...v}; // index signature lost
let v4 = {...v, a: ''}; // same as above
let v5 = {a: 1, ...v}; // index signature lost, should be '{a: number, [x: string]: number | string}'
let v6 = {[Number()]: 1, ...v}; // empty object type ò,Ó, should be '{[x: string]: number | string}'

Expected behavior:
Index signature exists on all object types.

Actual behavior:
Index signature is lost if object literal contains another property assignment. I'm not entirely sure what the type of v6 should be.

Playground Link: https://agentcooper.github.io/typescript-play/#code/CYUwxgNghgTiAEA3WSBc8BK4D2NgB4BnAFxgEsA7AcwBp4TzqA+AbgCg2IRikAmeALzwA3gDpxiAL4t4AelnwA7rgDWhTtyQBmQSKjoA5AbrjRUmfPiVQAD3pkqFKMQCuceBGwkNPRABZdMQk6fXgjaTkFQigAWwQoQngoACNsRBAfJABWQNCARhMJCMtrEDtCBydXd08SOkIAC2wXCGB4ZIQDYVCKFxiOmDoAbRt0BkoqAF10Xv6QGHgAH3pSCckDTMQANkChgDk+gYAKAEpp+AL4U3NI+BAYgAdiAE94bGSAK3AeF4eEACeaABl+pNFptDphYQjMarajnWYDJYrRhUdZAA

Related Issues:
#16694
#16373

Activity

ghost added
BugA bug in TypeScript
on Sep 21, 2018
added
SuggestionAn idea for TypeScript
and removed
BugA bug in TypeScript
on Oct 9, 2018
RyanCavanaugh

RyanCavanaugh commented on Oct 9, 2018

@RyanCavanaugh
Member

I think it's extremely arguable one way or the other. Certainly if you introduce a non-conforming property, the original intent of the index signature is lost.

added a commit that references this issue on Dec 27, 2018
a626e4e
jsingerlenovo

jsingerlenovo commented on Mar 18, 2021

@jsingerlenovo

Object.assign is able to handle the types correctly, why can't Object Spread?

declare var v: Record<string, string>;

const v3 = { a: '', ...v }; // index signature lost, type is only { a: string; }
const v7 = Object.assign({ a: '' }, v);  // works, type is { a: string; } & Record<string, string>

const s3 = v3.stuff; // Property 'stuff' does not exist on type '{ a: string; }'.ts(2339)
const s7 = v7.stuff; // works fine
joealden

joealden commented on Jan 10, 2022

@joealden

As mentioned above, the type inference of Object.assign currently differs from the type inference of the object spread syntax. While to my understanding their behaviors don't map 1:1, in this scenario, I would personally expect them to both result in the same types being inferred. I'm not advocating for which way to type them (although personally I think that the less restrictive option seems more intuitive), but I do think that it makes sense for these two "object merge" techniques to be consistent?

Here's an newer playground link that shows that this behaviour still exists in TS 4.5:

https://www.typescriptlang.org/play?#code/MYewdgzgLgBA5gUygIQIYQQeQEYCsHCwC8MAFAJQBcMASgSAE4AmAPNAwJZhwA0M7XODAA+MAK5gmCAGZcETAHwwiSgN4AoGFpgMkYhmBiqYABwYgTCBlACeARmoAiRzAC+AbnUf160JFggeARQdsowOPiEAHToEBxwYKSIKOhYQYQUfMZmFla2AExOUAjQLq7knn4QIAA2CFE1IHCkgZEhUTmW1vYVPlUB6VD5YcZRY8loGBHBmabmXQVFJVBlleDVdQ1NLYP5HfN5PZ7qQA

bmillwood

bmillwood commented on May 2, 2022

@bmillwood

I was linked here from a StackOverflow question I asked, after noticing during code review a variable being assigned an incorrect type in a way that the compiler did not catch. My minimal reproduction:

const br: Record<string, number> = {b: 0};
const abr: Record<string, string> = {a: "", ...br};
console.log(abr);

Here abr contains both string and number values, despite the type saying it should only contain strings. It feels like in the presence of this bug I either need to manually type-check spread operators where I see them, or else avoid using them at all.

21 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    In DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @bmillwood@fatcerberus@RyanCavanaugh@vincerubinetti@joealden

        Issue actions

          Object spread drops index signature · Issue #27273 · microsoft/TypeScript