From 732b10f65ef91cee7aa5df2eeba10521cde33c27 Mon Sep 17 00:00:00 2001 From: Ruben Grimm Date: Wed, 21 Feb 2024 09:53:44 +0100 Subject: [PATCH] Fix: Copy array/tuple-logic from DelimiterCasedPropertiesDeep to CamelCasedPropertiesDeep to fix changing tuple-type to array-type --- source/camel-cased-properties-deep.d.ts | 43 ++++++++++++++++++--- source/delimiter-cased-properties-deep.d.ts | 2 + test-d/camel-cased-properties-deep.ts | 3 ++ 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/source/camel-cased-properties-deep.d.ts b/source/camel-cased-properties-deep.d.ts index b44482be6..8ba3491d7 100644 --- a/source/camel-cased-properties-deep.d.ts +++ b/source/camel-cased-properties-deep.d.ts @@ -1,4 +1,5 @@ import type {CamelCase, CamelCaseOptions} from './camel-case'; +import type {UnknownArray} from './unknown-array'; /** Convert object properties to camel case recursively. @@ -44,11 +45,43 @@ const result: CamelCasedPropertiesDeep = { @category Template literal @category Object */ -export type CamelCasedPropertiesDeep = Value extends Function +export type CamelCasedPropertiesDeep< + Value, + Options extends CamelCaseOptions = {preserveConsecutiveUppercase: true}, +> = Value extends Function ? Value - : Value extends Array - ? Array> + : Value extends UnknownArray + ? CamelCasedPropertiesArrayDeep : Value extends Set - ? Set> : { - [K in keyof Value as CamelCase]: CamelCasedPropertiesDeep; + ? Set> + : { + [K in keyof Value as CamelCase]: CamelCasedPropertiesDeep< + Value[K], + Options + >; }; + +// This is a copy of DelimiterCasedPropertiesArrayDeep (see: delimiter-cased-properties-deep.d.ts). +// These types should be kept in sync. +type CamelCasedPropertiesArrayDeep = + Value extends [] + ? [] + : // Tailing spread array + Value extends [infer U, ...infer V] + ? [CamelCasedPropertiesDeep, ...CamelCasedPropertiesDeep] + : Value extends readonly [infer U, ...infer V] + ? readonly [CamelCasedPropertiesDeep, ...CamelCasedPropertiesDeep] + : // Leading spread array + Value extends readonly [...infer U, infer V] + ? [...CamelCasedPropertiesDeep, CamelCasedPropertiesDeep] + : Value extends readonly [...infer U, infer V] + ? readonly [ + ...CamelCasedPropertiesDeep, + CamelCasedPropertiesDeep, + ] + : // Array + Value extends Array + ? Array> + : Value extends ReadonlyArray + ? ReadonlyArray> + : never; diff --git a/source/delimiter-cased-properties-deep.d.ts b/source/delimiter-cased-properties-deep.d.ts index c6077c339..b91ff25eb 100644 --- a/source/delimiter-cased-properties-deep.d.ts +++ b/source/delimiter-cased-properties-deep.d.ts @@ -61,6 +61,8 @@ export type DelimiterCasedPropertiesDeep< >]: DelimiterCasedPropertiesDeep; }; +// This is a copy of CamelCasedPropertiesArrayDeep (see: camel-cased-properties-deep.d.ts). +// These types should be kept in sync. type DelimiterCasedPropertiesArrayDeep = Value extends [] ? [] diff --git a/test-d/camel-cased-properties-deep.ts b/test-d/camel-cased-properties-deep.ts index 5f79ebd2e..83c1a1d4d 100644 --- a/test-d/camel-cased-properties-deep.ts +++ b/test-d/camel-cased-properties-deep.ts @@ -19,6 +19,9 @@ expectType<{fooBAR: number; baz: {fooBAR: number; bARFoo: string}}>(baz); declare const biz: CamelCasedPropertiesDeep; expectType<{fooBar: number; baz: {fooBar: number; barFoo: string}}>(biz); +declare const tuple: CamelCasedPropertiesDeep<{tuple: [number, string, {D: string}]}>; +expectType<{tuple: [number, string, {d: string}]}>(tuple); + // Verify example type User = { UserId: number;