π Search Terms
This doesn't seem related to #31025. This is about the inconsistent behavior and specifically when exactOptionalPropertyTypes option is enabled.
π Version & Regression Information
Fails with v5.9.3.
β― Playground Link
https://www.typescriptlang.org/play/?exactOptionalPropertyTypes=true&ts=5.3.3#code/PTAEAEFMA8EMGMAuB5ADoglgewHawDYAKATlqpMYgJ4AqV5AzgFyiLECukAUF9eaACVIARwA8NAHygAvKADeAbUKgMOUAGtIVLADNQNALoBaAPwsaSgwF9QIUAGVYAW0ihYDVgAtXAI3YZ8RCNVUAADIWF-YkgAE1DWem4uOxJIBgoANzSvV1CAH1B2HBjIHVVY0IAaUBisNJwAckRQBgB3AnwsVpVmwFByXkTQAHUMRE9kHwArSCQZQREo2NE5WDMWtlUAc1ACopKynFirCWTgaSk5NxYGDZxt3eLS8piAblArHjt7dvxO1o8xrkHvtnvF+nxXCMxgBBYjEWBUOYRRYxUQKAAUN2IWx2hUeB1iAEoTAYTiBzqAFFitgYgA
π» Code
// @exactOptionalPropertyTypes: true
type Req<T> = {[P in keyof T]-?: T[P]} // Same as the built-in `Required` type
// Preserves the `| undefined`, doesn't swallow it β
type WithObject = Required<{a?: string | undefined}>
//=> { a: string | undefined; }
// Swallows the `| undefined` β
type WithArray = Required<[(string | undefined)?]>
//=> [string]
π Actual behavior
With exactOptionalPropertyTypes enabled, ?: string | undefined is different than ?: string. And mapped types respect this differentiation by not swallowing the | undefined with the -? mapping modifier.
// @exactOptionalPropertyTypes: true
type Req<T> = {[P in keyof T]-?: T[P]} // Same as the built-in `Required` type
// Preserves the `| undefined`, doesn't swallow it β
type WithObject = Req<{a?: string | undefined}>
//=> { a: string | undefined; }
However, when instantiated with arrays, the | undefined is swallowed during mapping. This is the issue!
// @exactOptionalPropertyTypes: true
type Req<T> = {[P in keyof T]-?: T[P]} // Same as the built-in `Required` type
// Swallows the `| undefined` β
type WithArray = Req<[(string | undefined)?]>
//=> [string]
And this is not just a display issue:
const withObject: WithObject = {a: undefined}; // β
Fine
const withArray: WithArray = [undefined]; // β Not fine
When exactOptionalPropertyTypes is disabled, the | undefined gets swallowed, and that is fine and unrelated to this particular issue.
// @exactOptionalPropertyTypes: false
type Req<T> = {[P in keyof T]-?: T[P]} // Same as the built-in `Required` type
// Swallows the `| undefined` β
type WithObject = Req<{a?: string | undefined}>
//=> { a: string; }
π Expected behavior
The behavior should be consistent. The | undefined bit should not be swallowed when mapping even for arrays.
Additional information about the issue
Here's another example:
// @exactOptionalPropertyTypes: true
type ToStringOrUnd<T> = {[P in keyof T]-?: string | undefined}
// Preserves the `| undefined` β
type WithObject = ToStringOrUnd<{a: 1; b?: 2}>
//=> { a: string | undefined; b: string | undefined; }
// Preserves the `| undefined` for the required element β
// But, doesn't preserve it for the optional element β
type WithArray = ToStringOrUnd<[1, 2?]>
//=> [string | undefined, string]
Playground Link
The -? mapping modifier seems to swallow the | undefined when operating on arrays, and specifically when operating with optional array elements.
π Search Terms
This doesn't seem related to #31025. This is about the inconsistent behavior and specifically when
exactOptionalPropertyTypesoption is enabled.π Version & Regression Information
Fails with
v5.9.3.β― Playground Link
https://www.typescriptlang.org/play/?exactOptionalPropertyTypes=true&ts=5.3.3#code/PTAEAEFMA8EMGMAuB5ADoglgewHawDYAKATlqpMYgJ4AqV5AzgFyiLECukAUF9eaACVIARwA8NAHygAvKADeAbUKgMOUAGtIVLADNQNALoBaAPwsaSgwF9QIUAGVYAW0ihYDVgAtXAI3YZ8RCNVUAADIWF-YkgAE1DWem4uOxJIBgoANzSvV1CAH1B2HBjIHVVY0IAaUBisNJwAckRQBgB3AnwsVpVmwFByXkTQAHUMRE9kHwArSCQZQREo2NE5WDMWtlUAc1ACopKynFirCWTgaSk5NxYGDZxt3eLS8piAblArHjt7dvxO1o8xrkHvtnvF+nxXCMxgBBYjEWBUOYRRYxUQKAAUN2IWx2hUeB1iAEoTAYTiBzqAFFitgYgA
π» Code
π Actual behavior
With
exactOptionalPropertyTypesenabled,?: string | undefinedis different than?: string. And mapped types respect this differentiation by not swallowing the| undefinedwith the-?mapping modifier.However, when instantiated with arrays, the
| undefinedis swallowed during mapping. This is the issue!And this is not just a display issue:
When
exactOptionalPropertyTypesis disabled, the| undefinedgets swallowed, and that is fine and unrelated to this particular issue.π Expected behavior
The behavior should be consistent. The
| undefinedbit should not be swallowed when mapping even for arrays.Additional information about the issue
Here's another example:
Playground Link
The
-?mapping modifier seems to swallow the| undefinedwhen operating on arrays, and specifically when operating with optional array elements.