-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Description
π 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
π» 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 fineWhen 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]The -? mapping modifier seems to swallow the | undefined when operating on arrays, and specifically when operating with optional array elements.