Typescript: Wrong `unknown` inference after `String()` in 4.1.0-dev.20200819

Created on 19 Aug 2020  路  6Comments  路  Source: microsoft/TypeScript


TypeScript Version: 4.1.0-dev.20200819


Search Terms: unknown inference string

Code

declare const thrownError: { code?: unknown; }

const thrownErrorCode = thrownError?.code && String(thrownError.code);

const str: string | undefined = thrownErrorCode;

Expected behavior: No Error

Actual behavior:
Error: _Type 'unknown' is not assignable to type 'string'.(2322)_ in the last line.

Playground Link:

https://www.typescriptlang.org/play?ts=4.1.0-dev.20200819#code/CYUwxgNghgTiAEYD2A7AzgF3hgFjJA7igKIz4wBc8A3okqAPxUCuKA1ioSgNzwC+AWABQw5Oiy58RUuQDC9BAF5seLjKQwGAOmSh4AMn3wAyhhgBLFAHMAFJLVkNOhQEpuw0akzxMlH2csreAAfeFZQADNLEGB4ZXtpRxh5UHchIA

Working version with 4.1.0-dev.20200818:

https://www.typescriptlang.org/play?ts=4.1.0-dev.20200818#code/CYUwxgNghgTiAEYD2A7AzgF3hgFjJA7igKIz4wBc8A3okqAPxUCuKA1ioSgNzwC+AWABQw5Oiy58RUuQDC9BAF5seLjKQwGAOmSh4AMn3wAyhhgBLFAHMAFJLVkNOhQEpuw0akzxMlH2csreAAfeFZQADNLEGB4ZXtpRxh5UHchIA

EDIT: Added missing | undefined

Working as Intended

All 6 comments

The error is correct though:
https://www.typescriptlang.org/play?ts=4.1.0-dev.20200818#code/C4TwDgpgBAKgFgJwPYHcB2BRByFQLxQDeUAxkgCYQBcUArmgNZqpoDcUAvgLABQvZaAM7AowRCyw4a8ZOklJcBQmUo16lAGYBLNBHIdW-JEJFjZmbAoDCFaATMTLCAPwA6FdABknqAGVgCDoA5gAUDnJO7rYAlIY8AsJQwgg0ycH4ouIRODaUcbzJrsBIADJIJACGADYQZSgQCFYVghAhsbxAA

Press run, and see:

[ERR]: Executed JavaScript Failed:
[ERR]: str is undefined

This is a known break coming up in 4.1, but pinging @andrewbranch just because we want to watch the issue tracker to gauge impact here.

@AlCalzone and @DanielRosenwasser: Okay forgot the | undefined ... but the argument stays the same => wrong inferred unknown => updated my repro sample.

@RyanCavanaugh duplicate of what? #39113 is the causing issue, not a duplicate ...

But change code to 0 and you'll have the same issue, right?

type ThrownError = { code: unknown; }

const thrownError: ThrownError = {code: 0};
const thrownErrorCode = thrownError?.code && String(thrownError.code);
const str: string = thrownErrorCode;

str.toLocaleLowerCase();

Yep, the actual domain of of str is string | false | 0 | 0n | NaN (if NaN were a type in TypeScript), so we leave that as unknown instead of giving you a huge union.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MartynasZilinskas picture MartynasZilinskas  路  3Comments

DanielRosenwasser picture DanielRosenwasser  路  3Comments

kyasbal-1994 picture kyasbal-1994  路  3Comments

jbondc picture jbondc  路  3Comments

remojansen picture remojansen  路  3Comments