TypeScript: Inconsitent (dis)allowing of undefined in spread operator

TypeScript Version: 2.7.0-dev.20171118

Code

declare let v1: undefined;
declare let v2: {[key: string]: string};
declare let v3: {[key: string]: string}|undefined;

let map: {[key: string]: string};
map = {...v1}; // FAILS
map = {...v2};
map = {...undefined}; // FAILS
map = {...v3}; // OK

Expected behavior:

  1. Consistency: undefined values are either allowed or disallowed in spread operator, regardless of whether they come explicitly, through a variable of undefined type, or through a variable of a variant type with an undefined branch.
  2. Ideally, backward compatibility with the previous versions.

Actual behavior:

  1. Values of “bare” undefined type are forbidden, while values of at least some X|undefined types are allowed.
  2. No backward compatibility, as the lines commented with “FAILS” are accepted by 2.5.3.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 17 (13 by maintainers)

Most upvoted comments

It’s useful to spread undefined or null into an object when dealing with conditionally adding a value:

type RequiredMap = {
  [key: string]: string;
};

type Params = {
  type?: string;
};

const tParams: Params = { type: '123' };

const ret: RequiredMap = {
  ...(tParams.type && { type: tParams.type }), // <-- fails
};

This is particularly valuable for any codebase that used to use Object.assign({}, because the following line was and is valid TS:

const ret2: RequiredMap = Object.assign({}, tParams.type && { type: tParams.type });

Using --fix for the prefer-object-spread would transform previously valid TS into invalid TS.