Skip to content

Object spread incorrectly introduces undefined value type in TS 4.2 #43045

Closed
@danvk

Description

@danvk

Bug Report

This was the one type error I got when I updated my project from TS 4.1 → 4.2. It's a false positive so I figured I'd file an issue in case others run into it as well. I assume this is considered an acceptable loss from this change in the release notes, but it is a false positive and regression from 4.1 nonetheless!

🔎 Search Terms

  • object spread undefined 4.2

Possibly related to #13195

🕗 Version & Regression Information

  • This changed between versions 4.1.5 and 4.2.2

⏯ Playground Link

Compiler Options
{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": 2,
    "target": "ES2017",
    "jsx": "React",
    "module": "ESNext"
  }
}

Playground Link: Provided

💻 Code

const param2 = Math.random() < 0.5 ? 'value2' : null;

const obj = {
    param1: 'value1',
    ...(param2 ? {param2} : {})
};

const query = Object.entries(obj).map(
    ([k, v]) => `${k}=${encodeURIComponent(v)}`
    //                                     ~
    // Argument of type 'string | undefined' is not assignable to parameter of type 'string | number | boolean'.
    //   Type 'undefined' is not assignable to type 'string | number | boolean'.(2345)
).join('&');
Output
"use strict";
const param2 = Math.random() < 0.5 ? 'value2' : null;
const obj = Object.assign({ param1: 'value1' }, (param2 ? { param2 } : {}));
const query = Object.entries(obj).map(([k, v]) => `${k}=${encodeURIComponent(v)}`
//                                     ~
// Argument of type 'string | undefined' is not assignable to parameter of type 'string | number | boolean'.
//   Type 'undefined' is not assignable to type 'string | number | boolean'.(2345)
).join('&');

🙁 Actual behavior

TypeScript says that v can be undefined, which it cannot. This leads to the type error in the call to encodeURIComponent.

🙂 Expected behavior

v can never be undefined at runtime, so the error is a false positive. This was not an error in TypeScript 4.1.

The root cause is that the type of obj is inferred as

const obj: {
    param2?: string | undefined;
    param1: string;
}

whereas in TS 4.1 the same inferred type shows up as:

const obj: {
    param2?: string;
    param1: string;
}

Metadata

Metadata

Assignees

Labels

Fix AvailableA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions