Skip to content

Possibility of undefined from optional properties is not honoured in spread #35983

Description

TypeScript Version: 3.6.3

Search Terms: spread optional undefined object properties property

Code

Here's an example of spreading an object with optional properties:

const myQueryDefaults: { a: number; } = { a: 1 };
const myQuery: { a?: number; } = {};

const result = { ...myQueryDefaults, ...myQuery };

// type is `number`
// runtime value is `number`
result.a;

The above example makes sense. However, an optional property does not only mean "this property may not exist" ({})—it also means "this property may exist with a value of undefined" ({ a: undefined }). (Related: #13195.)

As a result of this, the type information may mismatch the actual types at runtime:

const myQueryDefaults: { a: number; } = { a: 1 };
const myQuery: { a?: number;  } = { a: undefined };

const result = { ...myQueryDefaults, ...myQuery };

// type is `number`, but runtime value is `undefined`!!
// expected type: `number | undefined`
result.a;

… which could result in runtime exceptions:

result.a.toString(); // runtime exception, because `result.a` is `undefined`

Ideally optional properties would only mean "this property may not exist" (#13195), in which case the existing behaviour with spreading makes sense. However, in the interim, perhaps the behaviour of spreading should be changed?

Extracted from #13195 (comment)

Also potentially related: #31025

Activity

  1. changed the title [-]`undefined` Optional properties are not honoured in spread[/-] [+]Possibility of `undefined` from optional properties is not honoured in spread[/+] on Jan 3, 2020
  2. MartinJohns commented on Jan 3, 2020

    @MartinJohns
    Contributor

    However, in the interim, perhaps the behaviour of spreading should be changed?

    That would most likely break every codebase out there.

  3. RyanCavanaugh commented on Jan 6, 2020

    @RyanCavanaugh
    Member

    #13195 is the actionable version of this. This would be an unbelievably large and unergonomic breaking change.

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

    UnactionableThere isn't something we can do with this issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions