mirror of
https://github.com/chenasraf/DefinitelyTyped.git
synced 2026-05-18 01:49:01 +00:00
🤖 Merge PR #65820 feat: Add types for kebabcase-keys by @yutak23
This commit is contained in:
123
types/kebabcase-keys/index.d.ts
vendored
Normal file
123
types/kebabcase-keys/index.d.ts
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
// Type definitions for kebabcase-keys 1.0
|
||||
// Project: https://github.com/mattii/kebabcase-keys#readme
|
||||
// Definitions by: Yuta Katayama <https://github.com/yutak23>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// Minimum TypeScript Version: 4.1
|
||||
|
||||
/**
|
||||
* Return a default type if input type is nil.
|
||||
* @template T - Input type.
|
||||
* @template U - Default type.
|
||||
*/
|
||||
type WithDefault<T, U extends T> = T extends undefined | null ? U : T;
|
||||
|
||||
type CamelToKebab<S extends string> = S extends `${infer T}${infer U}`
|
||||
? `${T extends Capitalize<T> ? '-' : ''}${Lowercase<T>}${CamelToKebab<U>}`
|
||||
: S;
|
||||
|
||||
type PascalToKebab<S extends string> = CamelToKebab<Uncapitalize<S>>;
|
||||
|
||||
type SnakeToKebab<S extends string> = S extends `${infer T}_${infer U}` ? `${T}-${SnakeToKebab<U>}` : S;
|
||||
|
||||
type SpaceToKebab<S extends string> = S extends `${infer T}${Whitespace}${infer U}` ? `${T}-${SnakeToKebab<U>}` : S;
|
||||
|
||||
type ContainWordSeparatorsToKebab<S extends string> = S extends `${infer T}-${infer U}`
|
||||
? S
|
||||
: S extends `${infer T}_${infer U}`
|
||||
? SnakeToKebab<Lowercase<S>>
|
||||
: SpaceToKebab<S>;
|
||||
|
||||
type AnyCaseToKebab<S extends string> = S extends `${infer T}${WordSeparators}${infer U}`
|
||||
? ContainWordSeparatorsToKebab<S>
|
||||
: S extends Uppercase<S>
|
||||
? Lowercase<S>
|
||||
: S extends Capitalize<S>
|
||||
? PascalToKebab<S>
|
||||
: CamelToKebab<S>;
|
||||
|
||||
type KebabCase<S extends string | number | symbol> = S extends number
|
||||
? `${S}`
|
||||
: S extends symbol
|
||||
? never
|
||||
: S extends string
|
||||
? AnyCaseToKebab<S>
|
||||
: S;
|
||||
|
||||
type KebabCasedProperties<T, Deep extends boolean = false> = T extends readonly CustomJsonObject[]
|
||||
? {
|
||||
[Key in keyof T]: KebabCasedProperties<T[Key], Deep>;
|
||||
}
|
||||
: T extends CustomJsonObject
|
||||
? {
|
||||
[Key in keyof T as KebabCase<Key>]: T[Key] extends CustomJsonObject | CustomJsonObject[]
|
||||
? Deep[] extends Array<true>
|
||||
? KebabCasedProperties<T[Key], Deep>
|
||||
: T[Key]
|
||||
: T[Key];
|
||||
}
|
||||
: T;
|
||||
|
||||
interface Options {
|
||||
/**
|
||||
* Recurse nested objects and objects in arrays.
|
||||
* @default false
|
||||
*/
|
||||
readonly deep?: boolean;
|
||||
|
||||
/**
|
||||
* Exclude keys from being kebab-cased.
|
||||
* @default []
|
||||
*/
|
||||
readonly exclude?: ReadonlyArray<string | RegExp>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert object keys to kebabcase.
|
||||
* @param input - Object or array of objects to snake-case.
|
||||
* @param options - Options of conversion.
|
||||
*/
|
||||
declare function kebabcaseKeys<T extends CustomJsonObject | CustomJsonObject[], OptionsType extends Options>(
|
||||
input: T,
|
||||
options?: OptionsType,
|
||||
): KebabCasedProperties<T, WithDefault<OptionsType['deep'], false>>;
|
||||
|
||||
export = kebabcaseKeys;
|
||||
|
||||
// Extended versions of https://github.com/sindresorhus/type-fest#json
|
||||
type CustomJsonObject = { [Key in string]: CustomJsonValue } & {
|
||||
[Key in string]?: CustomJsonValue | undefined;
|
||||
};
|
||||
type CustomJsonValue = JsonPrimitive | object | CustomJsonObject | CustomJsonArray;
|
||||
type CustomJsonArray = CustomJsonValue[] | readonly CustomJsonValue[];
|
||||
|
||||
// based on https://github.com/DefinitelyTyped/DefinitelyTyped/pull/59806#pullrequestreview-942584759
|
||||
// Copied from https://github.com/sindresorhus/type-fest
|
||||
type JsonPrimitive = string | number | boolean | null;
|
||||
type WordSeparators = '-' | '_' | Whitespace;
|
||||
type Whitespace =
|
||||
| '\u{9}' // '\t'
|
||||
| '\u{A}' // '\n'
|
||||
| '\u{B}' // '\v'
|
||||
| '\u{C}' // '\f'
|
||||
| '\u{D}' // '\r'
|
||||
| '\u{20}' // ' '
|
||||
| '\u{85}'
|
||||
| '\u{A0}'
|
||||
| '\u{1680}'
|
||||
| '\u{2000}'
|
||||
| '\u{2001}'
|
||||
| '\u{2002}'
|
||||
| '\u{2003}'
|
||||
| '\u{2004}'
|
||||
| '\u{2005}'
|
||||
| '\u{2006}'
|
||||
| '\u{2007}'
|
||||
| '\u{2008}'
|
||||
| '\u{2009}'
|
||||
| '\u{200A}'
|
||||
| '\u{2028}'
|
||||
| '\u{2029}'
|
||||
| '\u{202F}'
|
||||
| '\u{205F}'
|
||||
| '\u{3000}'
|
||||
| '\u{FEFF}';
|
||||
52
types/kebabcase-keys/kebabcase-keys-tests.ts
Normal file
52
types/kebabcase-keys/kebabcase-keys-tests.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import kebabcaseKeys = require('kebabcase-keys');
|
||||
|
||||
class Point {
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
constructor(x: number, y: number) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
interface Person {
|
||||
name: string;
|
||||
age: number;
|
||||
}
|
||||
|
||||
const point = new Point(0, 10);
|
||||
const person: Person = {
|
||||
name: 'John',
|
||||
age: 30,
|
||||
};
|
||||
const symbol = Symbol('foo');
|
||||
|
||||
kebabcaseKeys({}); // $ExpectType {}
|
||||
kebabcaseKeys({ foo_bar: true }); // $ExpectType { "foo-bar": true; }
|
||||
kebabcaseKeys({ foo_bar: true, nested: { unicorn_rainbow: true } }); // $ExpectType { "foo-bar": true; nested: { unicorn_rainbow: true; }; }
|
||||
kebabcaseKeys({ foo_bar: true, nested: { unicorn_rainbow: true } }, { deep: true }); // $ExpectType { "foo-bar": true; nested: { "unicorn-rainbow": true; }; }
|
||||
|
||||
kebabcaseKeys([]); // $ExpectType never[]
|
||||
kebabcaseKeys([{}]); // $ExpectType {}[]
|
||||
kebabcaseKeys([{ foo_bar: true }]); // $ExpectType { "foo-bar": true; }[]
|
||||
kebabcaseKeys([{ foo_bar: true, nested: { unicorn_rainbow: true } }]); // $ExpectType { "foo-bar": true; nested: { unicorn_rainbow: true; }; }[]
|
||||
kebabcaseKeys([{ foo_bar: true, nested: { unicorn_rainbow: true } }], { deep: true }); // $ExpectType { "foo-bar": true; nested: { "unicorn-rainbow": true; }; }[]
|
||||
|
||||
kebabcaseKeys({ 123: 123 }); // $ExpectType { 123: number; }
|
||||
kebabcaseKeys({ [symbol]: 'symbol' }); // $ExpectType {}
|
||||
|
||||
kebabcaseKeys({ camelCase: 'camelCase' }); // $ExpectType { "camel-case": string; }
|
||||
kebabcaseKeys({ PascalCase: 'PascalCase' }); // $ExpectType { "pascal-case": string; }
|
||||
kebabcaseKeys({ snake_case: 'snake_case' }); // $ExpectType { "snake-case": string; }
|
||||
kebabcaseKeys({ 'kebabu-case': 'kebabu-case' }); // $ExpectType { "kebabu-case": string; }
|
||||
kebabcaseKeys({ Hogehoge: new Date() }); // $ExpectType { hogehoge: Date; }
|
||||
kebabcaseKeys({ UPPERCASE: 'UPPERCASE' }); // $ExpectType { uppercase: string; }
|
||||
kebabcaseKeys({ lowercase: 'lowercase' }); // $ExpectType { lowercase: string; }
|
||||
|
||||
kebabcaseKeys({ point_class: point }); // $ExpectType { "point-class": Point; }
|
||||
kebabcaseKeys({ person_interface: person }); // $ExpectType { "person-interface": Person; }
|
||||
|
||||
// @ts-expect-error
|
||||
kebabcaseKeys(['']);
|
||||
23
types/kebabcase-keys/tsconfig.json
Normal file
23
types/kebabcase-keys/tsconfig.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": [
|
||||
"es6"
|
||||
],
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictNullChecks": true,
|
||||
"baseUrl": "../",
|
||||
"typeRoots": [
|
||||
"../"
|
||||
],
|
||||
"types": [],
|
||||
"noEmit": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"files": [
|
||||
"index.d.ts",
|
||||
"kebabcase-keys-tests.ts"
|
||||
]
|
||||
}
|
||||
1
types/kebabcase-keys/tslint.json
Normal file
1
types/kebabcase-keys/tslint.json
Normal file
@@ -0,0 +1 @@
|
||||
{ "extends": "@definitelytyped/dtslint/dt.json" }
|
||||
Reference in New Issue
Block a user