Skip to content

Commit

Permalink
Fix CamelCaseKeys type.
Browse files Browse the repository at this point in the history
T[P] in the type definition of CamelCaseKeys could be anything and did not always satisfy the constraint of the generics argument T.
  • Loading branch information
Masa-Shin committed Aug 29, 2022
1 parent 1082010 commit e398e18
Showing 1 changed file with 61 additions and 59 deletions.
120 changes: 61 additions & 59 deletions index.d.ts
Expand Up @@ -43,31 +43,33 @@ export type CamelCaseKeys<
StopPaths extends readonly string[] = EmptyTuple,
Path extends string = '',
> = T extends readonly any[]
// Handle arrays or tuples.
// Handle arrays or tuples.
? {
[P in keyof T]: T[P] extends Record<string, any> | readonly any[]
// eslint-disable-next-line @typescript-eslint/ban-types
[P in keyof T]: {} extends CamelCaseKeys<T[P]>
? T[P]
: CamelCaseKeys<
T[P],
Deep,
IsPascalCase,
Exclude,
StopPaths
>;
? {} extends CamelCaseKeys<T[P]>
? T[P]
: CamelCaseKeys<
T[P],
Deep,
IsPascalCase,
Exclude,
StopPaths
>
: T[P];
}
: T extends Record<string, any>
// Handle objects.
// Handle objects.
? {
[P in keyof T as [IsInclude<Exclude, P>] extends [true]
[P in keyof T as[IsInclude<Exclude, P>] extends [true]
? P
: [IsPascalCase] extends [true]
? PascalCase<P>
: CamelCase<P>]: [IsInclude<StopPaths, AppendPath<Path, P & string>>] extends [
true,
]
? T[P]
// eslint-disable-next-line @typescript-eslint/ban-types
// eslint-disable-next-line @typescript-eslint/ban-types
: {} extends CamelCaseKeys<T[P]>
? T[P]
: [Deep] extends [true]
Expand All @@ -81,69 +83,69 @@ export type CamelCaseKeys<
>
: T[P];
}
// Return anything else as-is.
// Return anything else as-is.
: T;

type Options = {
/**
Recurse nested objects and objects in arrays.
Recurse nested objects and objects in arrays.
@default false
*/
@default false
*/
readonly deep?: boolean;

/**
Exclude keys from being camel-cased.
Exclude keys from being camel-cased.
If this option can be statically determined, it's recommended to add `as const` to it.
If this option can be statically determined, it's recommended to add `as const` to it.
@default []
*/
@default []
*/
readonly exclude?: ReadonlyArray<string | RegExp>;

/**
Exclude children at the given object paths in dot-notation from being camel-cased. For example, with an object like `{a: {b: '🦄'}}`, the object path to reach the unicorn is `'a.b'`.
If this option can be statically determined, it's recommended to add `as const` to it.
@default []
@example
```
import camelcaseKeys from 'camelcase-keys';
camelcaseKeys({
a_b: 1,
a_c: {
c_d: 1,
c_e: {
e_f: 1
}
}
}, {
deep: true,
stopPaths: [
'a_c.c_e'
]
}),
// {
// aB: 1,
// aC: {
// cD: 1,
// cE: {
// e_f: 1
// }
// }
// }
```
*/
Exclude children at the given object paths in dot-notation from being camel-cased. For example, with an object like `{a: {b: '🦄'}}`, the object path to reach the unicorn is `'a.b'`.
If this option can be statically determined, it's recommended to add `as const` to it.
@default []
@example
```
import camelcaseKeys from 'camelcase-keys';
camelcaseKeys({
a_b: 1,
a_c: {
c_d: 1,
c_e: {
e_f: 1
}
}
}, {
deep: true,
stopPaths: [
'a_c.c_e'
]
}),
// {
// aB: 1,
// aC: {
// cD: 1,
// cE: {
// e_f: 1
// }
// }
// }
```
*/
readonly stopPaths?: readonly string[];

/**
Uppercase the first character as in `bye-bye` → `ByeBye`.
Uppercase the first character as in `bye-bye` → `ByeBye`.
@default false
*/
@default false
*/
readonly pascalCase?: boolean;
};

Expand Down

0 comments on commit e398e18

Please sign in to comment.