import type {ApplyDefaultOptions} from './internal/index.d.ts'; import type {_DefaultWordsOptions, Words, WordsOptions} from './words.d.ts'; /** CamelCase options. @see {@link CamelCase} */ export type CamelCaseOptions = WordsOptions & { /** Whether to preserved consecutive uppercase letter. @default false */ preserveConsecutiveUppercase?: boolean; /** Whether to preserve leading underscores. This matches the behavior of the [`camelcase`](https://github.com/sindresorhus/camelcase) package v9+. @default false */ preserveLeadingUnderscores?: boolean; }; export type _DefaultCamelCaseOptions = _DefaultWordsOptions & { preserveConsecutiveUppercase: false; preserveLeadingUnderscores: false; }; /** Extract leading underscores from a string. @example ``` type A = LeadingUnderscores<'__foo_bar'>; //=> '__' type B = LeadingUnderscores<'foo_bar'>; //=> '' ``` */ type LeadingUnderscores = Type extends `_${infer Rest}` ? LeadingUnderscores : Underscores; /** Convert an array of words to camel-case. */ type CamelCaseFromArray< Words extends string[], Options extends Required, OutputString extends string = '', > = Words extends [ infer FirstWord extends string, ...infer RemainingWords extends string[], ] ? Options['preserveConsecutiveUppercase'] extends true ? `${Capitalize}${CamelCaseFromArray}` : `${Capitalize>}${CamelCaseFromArray}` : OutputString; /** Convert a string literal to camel-case. This can be useful when, for example, converting some kebab-cased command-line flags or a snake-cased database result. By default, consecutive uppercase letter are preserved. See {@link CamelCaseOptions.preserveConsecutiveUppercase preserveConsecutiveUppercase} option to change this behaviour. Use the `preserveLeadingUnderscores` option to retain leading underscores, matching the runtime behavior of [`camelcase`](https://github.com/sindresorhus/camelcase) v9+. @example ``` import type {CamelCase} from 'type-fest'; // Simple const someVariable: CamelCase<'foo-bar'> = 'fooBar'; const preserveConsecutiveUppercase: CamelCase<'foo-BAR-baz', {preserveConsecutiveUppercase: true}> = 'fooBARBaz'; const splitOnPunctuation: CamelCase<'foo-bar:BAZ', {splitOnPunctuation: true}> = 'fooBarBaz'; const preserveLeadingUnderscores: CamelCase<'_foo_bar', {preserveLeadingUnderscores: true}> = '_fooBar'; // Advanced type CamelCasedProperties = { [K in keyof T as CamelCase]: T[K] }; type RawOptions = { 'dry-run': boolean; 'full_family_name': string; foo: number; BAR: string; QUZ_QUX: number; 'OTHER-FIELD': boolean; }; const dbResult: CamelCasedProperties = { dryRun: true, fullFamilyName: 'bar.js', foo: 123, bar: 'foo', quzQux: 6, otherField: false, }; ``` @category Change case @category Template literal */ export type CamelCase = Type extends string ? string extends Type ? Type : `${Options['preserveLeadingUnderscores'] extends true ? LeadingUnderscores : '' }${Uncapitalize ? Lowercase : Type, Options>, ApplyDefaultOptions >>}` : Type; export {};