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
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.