diff --git a/readme.md b/readme.md index f9b603fc3..7c7862a3c 100644 --- a/readme.md +++ b/readme.md @@ -111,10 +111,20 @@ Click the type names for complete docs. *Note:* These require [TypeScript 4.1 or newer](https://devblogs.microsoft.com/typescript/announcing-typescript-4-1/#template-literal-types). - [`CamelCase`](ts41/camel-case.d.ts) – Convert a string literal to camel-case (`fooBar`). +- [`CamelCasedProperties`](ts41/camel-cased-properties.d.ts) – Convert object properties to camel-case (`fooBar`). +- [`CamelCasedPropertiesDeep`](ts41/camel-cased-properties-deep.d.ts) – Convert object properties to camel-case recursively (`fooBar`). - [`KebabCase`](ts41/kebab-case.d.ts) – Convert a string literal to kebab-case (`foo-bar`). +- [`KebabCasedProperties`](ts41/kebab-cased-properties.d.ts) – Convert a object properties to kebab-case recursively (`foo-bar`). +- [`KebabCasedPropertiesDeep`](ts41/kebab-cased-properties-deep.d.ts) – Convert object properties to kebab-case (`foo-bar`). - [`PascalCase`](ts41/pascal-case.d.ts) – Converts a string literal to pascal-case (`FooBar`) +- [`PascalCasedProperties`](ts41/pascal-cased-properties.d.ts) – Converts object properties to pascal-case (`FooBar`) +- [`PascalCasedPropertiesDeep`](ts41/pascal-cased-properties-deep.d.ts) – Converts object properties to pascal-case (`FooBar`) - [`SnakeCase`](ts41/snake-case.d.ts) – Convert a string literal to snake-case (`foo_bar`). +- [`SnakeCasedProperties`](ts41/snake-cased-properties-deep.d.ts) – Convert object properties to snake-case (`foo_bar`). +- [`SnakeCasedPropertiesDeep`](ts41/snake-cased-properties-deep.d.ts) – Convert object properties to snake-case recursively (`foo_bar`). - [`DelimiterCase`](ts41/delimiter-case.d.ts) – Convert a string literal to a custom string delimiter casing. +- [`DelimiterCasedProperties`](ts41/delimiter-cased-properties.d.ts) – Convert object properties to a custom string delimiter casing. +- [`DelimiterCasedPropertiesDeep`](ts41/delimiter-cased-properties-deep.d.ts) – Convert object properties to a custom string delimiter casing recursively. - [`Split`](ts41/split.d.ts) - Represents an array of strings split using a given character or character set. - [`Trim`](ts41/trim.d.ts) - Remove leading and trailing spaces from a string. - [`Get`](ts41/get.d.ts) - Get a deeply-nested property from an object using a key path, like [Lodash's `.get()`](https://lodash.com/docs/latest#get) function. diff --git a/test-d/camel-case.ts b/test-d/camel-case.ts index 9431d7c42..d3df04d35 100644 --- a/test-d/camel-case.ts +++ b/test-d/camel-case.ts @@ -38,7 +38,7 @@ const camelFromRepeatedSeparators: CamelCase<'foo____bar'> = 'fooBar'; expectType<'fooBar'>(camelFromRepeatedSeparators); // Verifying example -type CamelCasedProps = { +type CamelCasedProperties = { [K in keyof T as CamelCase]: T[K] }; @@ -48,7 +48,7 @@ interface RawOptions { foo: number; } -expectAssignable>({ +expectAssignable>({ dryRun: true, fullFamilyName: 'bar.js', foo: 123 diff --git a/test-d/camel-cased-properties-deep.ts b/test-d/camel-cased-properties-deep.ts new file mode 100644 index 000000000..23a9bd8cc --- /dev/null +++ b/test-d/camel-cased-properties-deep.ts @@ -0,0 +1,41 @@ +import {CamelCasedPropertiesDeep} from '../ts41/camel-cased-properties-deep'; +import {expectType} from 'tsd'; + +declare const foo: CamelCasedPropertiesDeep<{A: {B: number; C: Array<{D: string}>}}>; + +expectType<{a: {b: number; c: Array<{d: string}>}}>(foo); + +declare const fooBar: CamelCasedPropertiesDeep<() => {a: string}>; +expectType<() => {a: string}>(fooBar); + +declare const bar: CamelCasedPropertiesDeep>; +expectType>(bar); + +// Verify example +interface User { + UserId: number; + UserName: string; +} + +interface UserWithFriends { + UserInfo: User; + UserFriends: User[]; +} + +const result: CamelCasedPropertiesDeep = { + userInfo: { + userId: 1, + userName: 'Tom' + }, + userFriends: [ + { + userId: 2, + userName: 'Jerry' + }, + { + userId: 3, + userName: 'Spike' + } + ] +}; +expectType>(result); diff --git a/test-d/camel-cased-properties.ts b/test-d/camel-cased-properties.ts new file mode 100644 index 000000000..0263ca7c3 --- /dev/null +++ b/test-d/camel-cased-properties.ts @@ -0,0 +1,24 @@ +import {CamelCasedProperties} from '../ts41/camel-cased-properties'; +import {expectType} from 'tsd'; + +declare const foo: CamelCasedProperties<{A: number; B: {C: string}}>; + +expectType<{a: number; b: {C: string}}>(foo); + +declare const bar: CamelCasedProperties>; +expectType>(bar); + +declare const fooBar: CamelCasedProperties<() => {a: string}>; +expectType<() => {a: string}>(fooBar); + +// Verify example +interface User { + UserId: number; + UserName: string; +} + +const result: CamelCasedProperties = { + userId: 1, + userName: 'Tom' +}; +expectType>(result); diff --git a/test-d/delimiter-case.ts b/test-d/delimiter-case.ts index a92d62ad7..ed284c2f2 100644 --- a/test-d/delimiter-case.ts +++ b/test-d/delimiter-case.ts @@ -44,7 +44,7 @@ const delimiterFromRepeatedSeparators: DelimiterCase<'foo____bar', '#'> = 'foo## expectType<'foo####bar'>(delimiterFromRepeatedSeparators); // Verifying example -type OddCasedProps = { +type OddCasedProperties = { [K in keyof T as DelimiterCase]: T[K] }; @@ -54,7 +54,7 @@ interface CliOptions { foo: number; } -expectAssignable>({ +expectAssignable>({ 'dry#run': true, 'include#file': 'bar.js', foo: 123 diff --git a/test-d/delimiter-cased-properties-deep.ts b/test-d/delimiter-cased-properties-deep.ts new file mode 100644 index 000000000..1e34ffeb4 --- /dev/null +++ b/test-d/delimiter-cased-properties-deep.ts @@ -0,0 +1,40 @@ +import {expectType} from 'tsd'; +import {DelimiterCasedPropertiesDeep} from '../ts41/delimiter-cased-properties-deep'; + +declare const foo: DelimiterCasedPropertiesDeep<{helloWorld: {fooBar: string}}, '/'>; +expectType<{'hello/world': {'foo/bar': string}}>(foo); + +declare const fooBar: DelimiterCasedPropertiesDeep<() => {a: string}, '/'>; +expectType<() => {a: string}>(fooBar); + +declare const bar: DelimiterCasedPropertiesDeep, '-'>; +expectType>(bar); + +// Verify example +interface User { + userId: number; + userName: string; +} + +interface UserWithFriends { + userInfo: User; + userFriends: User[]; +} + +const result: DelimiterCasedPropertiesDeep = { + 'user-info': { + 'user-id': 1, + 'user-name': 'Tom' + }, + 'user-friends': [ + { + 'user-id': 2, + 'user-name': 'Jerry' + }, + { + 'user-id': 3, + 'user-name': 'Spike' + } + ] +}; +expectType>(result); diff --git a/test-d/delimiter-cased-properties.ts b/test-d/delimiter-cased-properties.ts new file mode 100644 index 000000000..0e4739f84 --- /dev/null +++ b/test-d/delimiter-cased-properties.ts @@ -0,0 +1,22 @@ +import {expectType} from 'tsd'; +import {DelimiterCasedProperties} from '../ts41/delimiter-cased-properties'; + +declare const foo: DelimiterCasedProperties<{helloWorld: {fooBar: string}}, '/'>; +expectType<{'hello/world': {fooBar: string}}>(foo); + +declare const bar: DelimiterCasedProperties, '-'>; +expectType>(bar); + +declare const fooBar: DelimiterCasedProperties<() => {a: string}, '-'>; +expectType<() => {a: string}>(fooBar); + +// Verify example +interface User { + userId: number; + userName: string; +} +const result: DelimiterCasedProperties = { + 'user-id': 1, + 'user-name': 'Tom' +}; +expectType>(result); diff --git a/test-d/kebab-cased-properties-deep.ts b/test-d/kebab-cased-properties-deep.ts new file mode 100644 index 000000000..23563e286 --- /dev/null +++ b/test-d/kebab-cased-properties-deep.ts @@ -0,0 +1,37 @@ +import {KebabCasedPropertiesDeep} from '../ts41/kebab-cased-properties-deep'; +import {expectType} from 'tsd'; + +declare const foo: KebabCasedPropertiesDeep<{helloWorld: {fooBar: string}}>; +expectType<{'hello-world': {'foo-bar': string}}>(foo); + +declare const bar: KebabCasedPropertiesDeep>; +expectType>(bar); + +// Verify example +interface User { + userId: number; + userName: string; +} + +interface UserWithFriends { + userInfo: User; + userFriends: User[]; +} + +const result: KebabCasedPropertiesDeep = { + 'user-info': { + 'user-id': 1, + 'user-name': 'Tom' + }, + 'user-friends': [ + { + 'user-id': 2, + 'user-name': 'Jerry' + }, + { + 'user-id': 3, + 'user-name': 'Spike' + } + ] +}; +expectType>(result); diff --git a/test-d/kebab-cased-properties.ts b/test-d/kebab-cased-properties.ts new file mode 100644 index 000000000..9d2d9bf6d --- /dev/null +++ b/test-d/kebab-cased-properties.ts @@ -0,0 +1,16 @@ +import {KebabCasedProperties} from '../ts41/kebab-cased-properties'; +import {expectType} from 'tsd'; + +declare const foo: KebabCasedProperties<{helloWorld: {fooBar: string}}>; +expectType<{'hello-world': {fooBar: string}}>(foo); + +// Verify example +interface User { + userId: number; + userName: string; +} +const result: KebabCasedProperties = { + 'user-id': 1, + 'user-name': 'Tom' +}; +expectType>(result); diff --git a/test-d/pascal-cased-properties-deep.ts b/test-d/pascal-cased-properties-deep.ts new file mode 100644 index 000000000..da192a858 --- /dev/null +++ b/test-d/pascal-cased-properties-deep.ts @@ -0,0 +1,40 @@ +import {PascalCasedPropertiesDeep} from '../ts41/pascal-cased-properties-deep'; +import {expectType} from 'tsd'; + +declare const foo: PascalCasedPropertiesDeep<{helloWorld: {fooBar: string}}>; +expectType<{HelloWorld: {FooBar: string}}>(foo); + +declare const fooBar: PascalCasedPropertiesDeep<() => {a: string}>; +expectType<() => {a: string}>(fooBar); + +declare const bar: PascalCasedPropertiesDeep>; +expectType>(bar); + +// Verify example +interface User { + userId: number; + userName: string; +} + +interface UserWithFriends { + userInfo: User; + userFriends: User[]; +} + +const result: PascalCasedPropertiesDeep = { + UserInfo: { + UserId: 1, + UserName: 'Tom' + }, + UserFriends: [ + { + UserId: 2, + UserName: 'Jerry' + }, + { + UserId: 3, + UserName: 'Spike' + } + ] +}; +expectType>(result); diff --git a/test-d/pascal-cased-properties.ts b/test-d/pascal-cased-properties.ts new file mode 100644 index 000000000..77851b85a --- /dev/null +++ b/test-d/pascal-cased-properties.ts @@ -0,0 +1,22 @@ +import {PascalCasedProperties} from '../ts41/pascal-cased-properties'; +import {expectType} from 'tsd'; + +declare const foo: PascalCasedProperties<{helloWorld: {fooBar: string}}>; +expectType<{HelloWorld: {fooBar: string}}>(foo); + +declare const bar: PascalCasedProperties>; +expectType>(bar); + +declare const fooBar: PascalCasedProperties<() => {a: string}>; +expectType<() => {a: string}>(fooBar); + +// Verify example +interface User { + userId: number; + userName: string; +} +const result: PascalCasedProperties = { + UserId: 1, + UserName: 'Tom' +}; +expectType>(result); diff --git a/test-d/snake-cased-properties-deep.ts b/test-d/snake-cased-properties-deep.ts new file mode 100644 index 000000000..0b27e187a --- /dev/null +++ b/test-d/snake-cased-properties-deep.ts @@ -0,0 +1,37 @@ +import {SnakeCasedPropertiesDeep} from '../ts41/snake-cased-properties-deep'; +import {expectType} from 'tsd'; + +declare const foo: SnakeCasedPropertiesDeep<{helloWorld: {fooBar: string}}>; +expectType<{hello_world: {foo_bar: string}}>(foo); + +declare const bar: SnakeCasedPropertiesDeep>; +expectType>(bar); + +// Verify example +interface User { + userId: number; + userName: string; +} + +interface UserWithFriends { + userInfo: User; + userFriends: User[]; +} + +const result: SnakeCasedPropertiesDeep = { + user_info: { + user_id: 1, + user_name: 'Tom' + }, + user_friends: [ + { + user_id: 2, + user_name: 'Jerry' + }, + { + user_id: 3, + user_name: 'Spike' + } + ] +}; +expectType>(result); diff --git a/test-d/snake-cased-properties.ts b/test-d/snake-cased-properties.ts new file mode 100644 index 000000000..b86d3dbe0 --- /dev/null +++ b/test-d/snake-cased-properties.ts @@ -0,0 +1,16 @@ +import {SnakeCasedProperties} from '../ts41/snake-cased-properties'; +import {expectType} from 'tsd'; + +declare const foo: SnakeCasedProperties<{helloWorld: {fooBar: string}}>; +expectType<{hello_world: {fooBar: string}}>(foo); + +// Verify example +interface User { + userId: number; + userName: string; +} +const result: SnakeCasedProperties = { + user_id: 1, + user_name: 'Tom' +}; +expectType>(result); diff --git a/ts41/camel-case.d.ts b/ts41/camel-case.d.ts index 4f9a67bc4..7135743d9 100644 --- a/ts41/camel-case.d.ts +++ b/ts41/camel-case.d.ts @@ -44,7 +44,7 @@ const someVariable: CamelCase<'foo-bar'> = 'fooBar'; // Advanced -type CamelCasedProps = { +type CamelCasedProperties = { [K in keyof T as CamelCase]: T[K] }; @@ -54,7 +54,7 @@ interface RawOptions { foo: number; } -const dbResult: CamelCasedProps = { +const dbResult: CamelCasedProperties = { dryRun: true, fullFamilyName: 'bar.js', foo: 123 diff --git a/ts41/camel-cased-properties-deep.d.ts b/ts41/camel-cased-properties-deep.d.ts new file mode 100644 index 000000000..7117a75b4 --- /dev/null +++ b/ts41/camel-cased-properties-deep.d.ts @@ -0,0 +1,48 @@ +import {CamelCase} from './camel-case'; + +/** +Convert object properties to camel case recursively. + +This can be useful when, for example, converting some API types from a different style. + +@see CamelCasedProperties +@see CamelCase + +@example +``` +interface User { + UserId: number; + UserName: string; +} + +interface UserWithFriends { + UserInfo: User; + UserFriends: User[]; +} + +const result: CamelCasedPropertiesDeep = { + userInfo: { + userId: 1, + userName: 'Tom', + }, + userFriends: [ + { + userId: 2, + userName: 'Jerry', + }, + { + userId: 3, + userName: 'Spike', + }, + ], +}; +``` +*/ +export type CamelCasedPropertiesDeep = Value extends Function + ? Value + : Value extends Array + ? Array> + : Value extends Set + ? Set> : { + [K in keyof Value as CamelCase]: CamelCasedPropertiesDeep; + }; diff --git a/ts41/camel-cased-properties.d.ts b/ts41/camel-cased-properties.d.ts new file mode 100644 index 000000000..ca315952c --- /dev/null +++ b/ts41/camel-cased-properties.d.ts @@ -0,0 +1,30 @@ +import {CamelCase} from './camel-case'; + +/** +Convert object properties to camel case but not recursively. + +This can be useful when, for example, converting some API types from a different style. + +@see CamelCasedPropertiesDeep +@see CamelCase + +@example +``` +interface User { + UserId: number; + UserName: string; +} + +const result: CamelCasedProperties = { + userId: 1, + userName: 'Tom', +}; +``` +*/ +export type CamelCasedProperties = Value extends Function + ? Value + : Value extends Array + ? Value + : { + [K in keyof Value as CamelCase]: Value[K]; + }; diff --git a/ts41/delimiter-case.d.ts b/ts41/delimiter-case.d.ts index 52f4eb992..a58ed5526 100644 --- a/ts41/delimiter-case.d.ts +++ b/ts41/delimiter-case.d.ts @@ -57,7 +57,7 @@ const someVariable: DelimiterCase<'fooBar', '#'> = 'foo#bar'; // Advanced -type OddlyCasedProps = { +type OddlyCasedProperties = { [K in keyof T as DelimiterCase]: T[K] }; @@ -67,7 +67,7 @@ interface SomeOptions { foo: number; } -const rawCliOptions: OddlyCasedProps = { +const rawCliOptions: OddlyCasedProperties = { 'dry#run': true, 'include#file': 'bar.js', foo: 123 diff --git a/ts41/delimiter-cased-properties-deep.d.ts b/ts41/delimiter-cased-properties-deep.d.ts new file mode 100644 index 000000000..741c4ad8a --- /dev/null +++ b/ts41/delimiter-cased-properties-deep.d.ts @@ -0,0 +1,54 @@ +import {DelimiterCase} from './delimiter-case'; + +/** +Convert object properties to delimiter case recursively. + +This can be useful when, for example, converting some API types from a different style. + +@see DelimiterCase +@see DelimiterCasedProperties + +@example +``` +interface User { + userId: number; + userName: string; +} + +interface UserWithFriends { + userInfo: User; + userFriends: User[]; +} + +const result: DelimiterCasedPropertiesDeep = { + 'user-info': { + 'user-id': 1, + 'user-name': 'Tom', + }, + 'user-friends': [ + { + 'user-id': 2, + 'user-name': 'Jerry', + }, + { + 'user-id': 3, + 'user-name': 'Spike', + }, + ], +}; +``` +*/ +export type DelimiterCasedPropertiesDeep< + Value, + Delimiter extends string +> = Value extends Function + ? Value + : Value extends Array + ? Array> + : Value extends Set + ? Set> : { + [K in keyof Value as DelimiterCase< + K, + Delimiter + >]: DelimiterCasedPropertiesDeep; + }; diff --git a/ts41/delimiter-cased-properties.d.ts b/ts41/delimiter-cased-properties.d.ts new file mode 100644 index 000000000..8a108a665 --- /dev/null +++ b/ts41/delimiter-cased-properties.d.ts @@ -0,0 +1,31 @@ +import {DelimiterCase} from './delimiter-case'; + +/** +Convert object properties to delimiter case but not recursively. + +This can be useful when, for example, converting some API types from a different style. + +@see DelimiterCase +@see DelimiterCasedPropertiesDeep + +@example +``` +interface User { + userId: number; + userName: string; +} + +const result: DelimiterCasedProperties = { + 'user-id': 1, + 'user-name': 'Tom', +}; +``` +*/ +export type DelimiterCasedProperties< + Value, + Delimiter extends string +> = Value extends Function + ? Value + : Value extends Array + ? Value + : { [K in keyof Value as DelimiterCase]: Value[K] }; diff --git a/ts41/kebab-case.d.ts b/ts41/kebab-case.d.ts index ba6a99d1f..47049c779 100644 --- a/ts41/kebab-case.d.ts +++ b/ts41/kebab-case.d.ts @@ -15,7 +15,7 @@ const someVariable: KebabCase<'fooBar'> = 'foo-bar'; // Advanced -type KebabCasedProps = { +type KebabCasedProperties = { [K in keyof T as KebabCase]: T[K] }; @@ -25,7 +25,7 @@ interface CliOptions { foo: number; } -const rawCliOptions: KebabCasedProps = { +const rawCliOptions: KebabCasedProperties = { 'dry-run': true, 'include-file': 'bar.js', foo: 123 diff --git a/ts41/kebab-cased-properties-deep.d.ts b/ts41/kebab-cased-properties-deep.d.ts new file mode 100644 index 000000000..cdca49945 --- /dev/null +++ b/ts41/kebab-cased-properties-deep.d.ts @@ -0,0 +1,41 @@ +import {DelimiterCasedPropertiesDeep} from './delimiter-cased-properties-deep'; + +/** +Convert object properties to kebab case recursively. + +This can be useful when, for example, converting some API types from a different style. + +@see KebabCase +@see KebabCasedProperties + +@example +``` +interface User { + userId: number; + userName: string; +} + +interface UserWithFriends { + userInfo: User; + userFriends: User[]; +} + +const result: KebabCasedPropertiesDeep = { + 'user-info': { + 'user-id': 1, + 'user-name': 'Tom', + }, + 'user-friends': [ + { + 'user-id': 2, + 'user-name': 'Jerry', + }, + { + 'user-id': 3, + 'user-name': 'Spike', + }, + ], +}; +``` +*/ +export type KebabCasedPropertiesDeep = DelimiterCasedPropertiesDeep; diff --git a/ts41/kebab-cased-properties.d.ts b/ts41/kebab-cased-properties.d.ts new file mode 100644 index 000000000..950cda5f7 --- /dev/null +++ b/ts41/kebab-cased-properties.d.ts @@ -0,0 +1,24 @@ +import {DelimiterCasedProperties} from './delimiter-cased-properties'; + +/** +Convert object properties to kebab case but not recursively. + +This can be useful when, for example, converting some API types from a different style. + +@see KebabCase +@see KebabCasedPropertiesDeep + +@example +``` +interface User { + userId: number; + userName: string; +} + +const result: KebabCasedProperties = { + 'user-id': 1, + 'user-name': 'Tom', +}; +``` +*/ +export type KebabCasedProperties = DelimiterCasedProperties; diff --git a/ts41/pascal-case.d.ts b/ts41/pascal-case.d.ts index bfb2a3627..35bd2fd18 100644 --- a/ts41/pascal-case.d.ts +++ b/ts41/pascal-case.d.ts @@ -23,7 +23,7 @@ interface RawOptions { foo: number; } -const dbResult: CamelCasedProps = { +const dbResult: CamelCasedProperties = { DryRun: true, FullFamilyName: 'bar.js', Foo: 123 diff --git a/ts41/pascal-cased-properties-deep.d.ts b/ts41/pascal-cased-properties-deep.d.ts new file mode 100644 index 000000000..6bcb9569e --- /dev/null +++ b/ts41/pascal-cased-properties-deep.d.ts @@ -0,0 +1,48 @@ +import {PascalCase} from './pascal-case'; + +/** +Convert object properties to pascal case recursively. + +This can be useful when, for example, converting some API types from a different style. + +@see PascalCase +@see PascalCasedProperties + +@example +``` +interface User { + userId: number; + userName: string; +} + +interface UserWithFriends { + userInfo: User; + userFriends: User[]; +} + +const result: PascalCasedPropertiesDeep = { + UserInfo: { + UserId: 1, + UserName: 'Tom', + }, + UserFriends: [ + { + UserId: 2, + UserName: 'Jerry', + }, + { + UserId: 3, + UserName: 'Spike', + }, + ], +}; +``` +*/ +export type PascalCasedPropertiesDeep = Value extends Function + ? Value + : Value extends Array + ? Array> + : Value extends Set + ? Set> : { + [K in keyof Value as PascalCase]: PascalCasedPropertiesDeep; + }; diff --git a/ts41/pascal-cased-properties.d.ts b/ts41/pascal-cased-properties.d.ts new file mode 100644 index 000000000..f4f8394e3 --- /dev/null +++ b/ts41/pascal-cased-properties.d.ts @@ -0,0 +1,28 @@ +import {PascalCase} from './pascal-case'; + +/** +Convert object properties to pascal case but not recursively. + +This can be useful when, for example, converting some API types from a different style. + +@see PascalCase +@see PascalCasedPropertiesDeep + +@example +``` +interface User { + userId: number; + userName: string; +} + +const result: PascalCasedProperties = { + UserId: 1, + UserName: 'Tom', +}; +``` +*/ +export type PascalCasedProperties = Value extends Function + ? Value + : Value extends Array + ? Value + : { [K in keyof Value as PascalCase]: Value[K] }; diff --git a/ts41/snake-case.d.ts b/ts41/snake-case.d.ts index 272b3d359..f8efb4bd5 100644 --- a/ts41/snake-case.d.ts +++ b/ts41/snake-case.d.ts @@ -15,7 +15,7 @@ const someVariable: SnakeCase<'fooBar'> = 'foo_bar'; // Advanced -type SnakeCasedProps = { +type SnakeCasedProperties = { [K in keyof T as SnakeCase]: T[K] }; @@ -25,7 +25,7 @@ interface ModelProps { foo: number; } -const dbResult: SnakeCasedProps = { +const dbResult: SnakeCasedProperties = { 'is_happy': true, 'full_family_name': 'Carla Smith', foo: 123 diff --git a/ts41/snake-cased-properties-deep.d.ts b/ts41/snake-cased-properties-deep.d.ts new file mode 100644 index 000000000..fb822a51e --- /dev/null +++ b/ts41/snake-cased-properties-deep.d.ts @@ -0,0 +1,41 @@ +import {DelimiterCasedPropertiesDeep} from './delimiter-cased-properties-deep'; + +/** +Convert object properties to snake case recursively. + +This can be useful when, for example, converting some API types from a different style. + +@see SnakeCase +@see SnakeCasedProperties + +@example +``` +interface User { + userId: number; + userName: string; +} + +interface UserWithFriends { + userInfo: User; + userFriends: User[]; +} + +const result: SnakeCasedPropertiesDeep = { + user_info: { + user_id: 1, + user_name: 'Tom', + }, + user_friends: [ + { + user_id: 2, + user_name: 'Jerry', + }, + { + user_id: 3, + user_name: 'Spike', + }, + ], +}; +``` +*/ +export type SnakeCasedPropertiesDeep = DelimiterCasedPropertiesDeep; diff --git a/ts41/snake-cased-properties.d.ts b/ts41/snake-cased-properties.d.ts new file mode 100644 index 000000000..6305ba894 --- /dev/null +++ b/ts41/snake-cased-properties.d.ts @@ -0,0 +1,24 @@ +import {DelimiterCasedProperties} from './delimiter-cased-properties'; + +/** +Convert object properties to snake case but not recursively. + +This can be useful when, for example, converting some API types from a different style. + +@see SnakeCase +@see SnakeCasedPropertiesDeep + +@example +``` +interface User { + userId: number; + userName: string; +} + +const result: SnakeCasedProperties = { + user_id: 1, + user_name: 'Tom', +}; +``` +*/ +export type SnakeCasedProperties = DelimiterCasedProperties;