From 7ebfa4a5a20f04edf217e43e9b86d79a004ae222 Mon Sep 17 00:00:00 2001 From: Andy Brenneke Date: Wed, 28 Aug 2024 10:57:25 -0700 Subject: [PATCH] Move IsEqual to be first in Exact comparison to short-circuit before distribution --- source/exact.d.ts | 15 ++++++++------- test-d/exact.ts | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/source/exact.d.ts b/source/exact.d.ts index a6c5686b4..923131d7f 100644 --- a/source/exact.d.ts +++ b/source/exact.d.ts @@ -53,13 +53,14 @@ onlyAcceptNameImproved(invalidInput); // Compilation error @category Utilities */ export type Exact = - // If the parameter is a primitive, return it as is immediately to avoid it being converted to a complex type - ParameterType extends Primitive ? ParameterType - // If the parameter is an unknown, return it as is immediately to avoid it being converted to a complex type - : IsUnknown extends true ? unknown - // If the parameter is a Function, return it as is because this type is not capable of handling function, leave it to TypeScript - : ParameterType extends Function ? ParameterType - : IsEqual extends true ? ParameterType + // Before distributing, check if the two types are equal and if so, return the parameter type immediately + IsEqual extends true ? ParameterType + // If the parameter is a primitive, return it as is immediately to avoid it being converted to a complex type + : ParameterType extends Primitive ? ParameterType + // If the parameter is an unknown, return it as is immediately to avoid it being converted to a complex type + : IsUnknown extends true ? unknown + // If the parameter is a Function, return it as is because this type is not capable of handling function, leave it to TypeScript + : ParameterType extends Function ? ParameterType // Convert union of array to array of union: A[] & B[] => (A & B)[] : ParameterType extends unknown[] ? Array, ArrayElement>> // In TypeScript, Array is a subtype of ReadonlyArray, so always test Array before ReadonlyArray. diff --git a/test-d/exact.ts b/test-d/exact.ts index f74f8ad86..495294447 100644 --- a/test-d/exact.ts +++ b/test-d/exact.ts @@ -537,3 +537,19 @@ import type {Exact, Opaque} from '../index'; // @ts-expect-error function_(withExcessSurname); } + +// Spec - recursive type with union +// @see https://github.com/sindresorhus/type-fest/issues/948 +{ + type A = { + a: Expected; + }; + type B = { + b: string; + }; + type Expected = A | B; + + const function_ = >(arguments_: T) => arguments_; + + function_({} as Expected); +}