Skip to content

Commit

Permalink
DelimiterCasedPropertiesDeep: Improve array handling (#744)
Browse files Browse the repository at this point in the history
  • Loading branch information
Emiyaaaaa committed Nov 13, 2023
1 parent 8fa831e commit 59411c8
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 9 deletions.
41 changes: 32 additions & 9 deletions source/delimiter-cased-properties-deep.d.ts
@@ -1,4 +1,5 @@
import type {DelimiterCase} from './delimiter-case';
import type {UnknownArray} from './unknown-array';

/**
Convert object properties to delimiter case recursively.
Expand Down Expand Up @@ -49,12 +50,34 @@ export type DelimiterCasedPropertiesDeep<
Delimiter extends string,
> = Value extends Function | Date | RegExp
? Value
: Value extends Array<infer U>
? Array<DelimiterCasedPropertiesDeep<U, Delimiter>>
: Value extends Set<infer U>
? Set<DelimiterCasedPropertiesDeep<U, Delimiter>> : {
[K in keyof Value as DelimiterCase<
K,
Delimiter
>]: DelimiterCasedPropertiesDeep<Value[K], Delimiter>;
};
: Value extends string
? DelimiterCase<Value, Delimiter>
: Value extends UnknownArray
? DelimiterCasedPropertiesArrayDeep<Value, Delimiter>
: Value extends Set<infer U>
? Set<DelimiterCasedPropertiesDeep<U, Delimiter>> : {
[K in keyof Value as DelimiterCase<
K,
Delimiter
>]: DelimiterCasedPropertiesDeep<Value[K], Delimiter>;
};

type DelimiterCasedPropertiesArrayDeep<Value extends UnknownArray, Delimiter extends string> =
Value extends []
? []
// Tailing spread array
: Value extends [infer U, ...infer V]
? [DelimiterCasedPropertiesDeep<U, Delimiter>, ...DelimiterCasedPropertiesDeep<V, Delimiter>]
: Value extends readonly [infer U, ...infer V]
? readonly [DelimiterCasedPropertiesDeep<U, Delimiter>, ...DelimiterCasedPropertiesDeep<V, Delimiter>]
// Leading spread array
: Value extends readonly [...infer U, infer V]
? [...DelimiterCasedPropertiesDeep<U, Delimiter>, DelimiterCasedPropertiesDeep<V, Delimiter>]
: Value extends readonly [...infer U, infer V]
? readonly [...DelimiterCasedPropertiesDeep<U, Delimiter>, DelimiterCasedPropertiesDeep<V, Delimiter>]
// Array
: Value extends Array<infer U>
? Array<DelimiterCasedPropertiesDeep<U, Delimiter>>
: Value extends ReadonlyArray<infer U>
? ReadonlyArray<DelimiterCasedPropertiesDeep<U, Delimiter>>
: never;
24 changes: 24 additions & 0 deletions test-d/delimiter-cased-properties-deep.ts
Expand Up @@ -46,3 +46,27 @@ const result: DelimiterCasedPropertiesDeep<UserWithFriends, '-'> = {
],
};
expectType<DelimiterCasedPropertiesDeep<UserWithFriends, '-'>>(result);

// Test object key properties
declare const key: DelimiterCasedPropertiesDeep<{readonly userId?: number}, '-'>;
expectType<{readonly 'user-id'?: number}>(key);

/** Test Array */
// Test for tuple
declare const tuple: DelimiterCasedPropertiesDeep<['userId', 'userName'], '-'>;
expectType<['user-id', 'user-name']>(tuple);
// Test for readonly
declare const readonlyTuple: DelimiterCasedPropertiesDeep<readonly ['userId', 'userName'], '-'>;
expectType<readonly ['user-id', 'user-name']>(readonlyTuple);
// Test for array
declare const array: DelimiterCasedPropertiesDeep<Array<'userId'>, '-'>;
expectType<Array<'user-id'>>(array);
// Test for readonly array
declare const readonlyArray: DelimiterCasedPropertiesDeep<ReadonlyArray<'userId'>, '-'>;
expectType<ReadonlyArray<'user-id'>>(readonlyArray);
// Test for tailing spread array
declare const tailingSpreadArray: DelimiterCasedPropertiesDeep<['userId', 'userName', ...Array<'userAge'>], '-'>;
expectType<['user-id', 'user-name', ...Array<'user-age'>]>(tailingSpreadArray);
// Test for leading spread array
declare const leadingSpreadArray: DelimiterCasedPropertiesDeep<[...Array<'userId'>, 'userName', 'userAge'], '-'>;
expectType<[...Array<'user-id'>, 'user-name', 'user-age']>(leadingSpreadArray);

0 comments on commit 59411c8

Please sign in to comment.