From 20e71e9b6d9bbc9a849c4a13ea2347086dd0a1eb Mon Sep 17 00:00:00 2001 From: Som Shekhar Mukherjee <49264891+som-sm@users.noreply.github.com> Date: Wed, 11 Dec 2024 03:17:41 +0530 Subject: [PATCH] `SharedUnionFields`: Simplify implementation (#1000) --- source/shared-union-fields.d.ts | 30 +++++++++++------------------- test-d/shared-union-fields.ts | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/source/shared-union-fields.d.ts b/source/shared-union-fields.d.ts index 427bd9cf4..bce1e9c0c 100644 --- a/source/shared-union-fields.d.ts +++ b/source/shared-union-fields.d.ts @@ -1,5 +1,6 @@ import type {NonRecursiveType, IsUnion} from './internal'; import type {IsNever} from './is-never'; +import type {Simplify} from './simplify'; import type {UnknownArray} from './unknown-array'; /** @@ -62,22 +63,13 @@ function displayPetInfo(petInfo: SharedUnionFields) { @category Object @category Union */ -export type SharedUnionFields = -// If `Union` is not a union type, return `Union` directly. -IsUnion extends false - ? Union - // `Union extends` will convert `Union` - // to a [distributive conditionaltype](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types). - // But this is not what we want, so we need to wrap `Union` with `[]` to prevent it. - : [Union] extends [NonRecursiveType | ReadonlyMap | ReadonlySet | UnknownArray] - ? Union - : [Union] extends [object] - // `keyof Union` can extract the same key in union type, if there is no same key, return never. - ? keyof Union extends infer Keys - ? IsNever extends false - ? { - [Key in keyof Union]: Union[Key] - } - : {} - : Union - : Union; +type SharedUnionFields = +Extract | ReadonlySet | UnknownArray> extends infer SkippedMembers + ? Exclude extends infer RelevantMembers + ? + | SkippedMembers + | (IsNever extends true + ? never + : Simplify>) + : never + : never; diff --git a/test-d/shared-union-fields.ts b/test-d/shared-union-fields.ts index 3ebef2559..c26477ba3 100644 --- a/test-d/shared-union-fields.ts +++ b/test-d/shared-union-fields.ts @@ -1,5 +1,6 @@ import {expectType} from 'tsd'; import type {SharedUnionFields} from '../index'; +import type {NonRecursiveType} from '../source/internal'; type TestingType = { function: (() => void); @@ -82,3 +83,17 @@ expectType<{union: 'test1' | 'test2' | {a: number}}>(union); declare const unionWithOptional: SharedUnionFields<{a?: string; foo: number} | {a: string; bar: string}>; expectType<{a?: string}>(unionWithOptional); + +// Non-recursive types +expectType | Map>({} as Set | Map); +expectType>({} as string[] | Set); +expectType({} as NonRecursiveType); + +// Mix of non-recursive and recursive types +expectType<{a: string | number} | undefined>({} as SharedUnionFields<{a: string} | {a: number; b: true} | undefined>); +expectType({} as SharedUnionFields); +expectType({} as SharedUnionFields); + +// Boundary types +expectType({} as SharedUnionFields); +expectType({} as SharedUnionFields);