mirror of
https://github.com/sindresorhus/type-fest.git
synced 2025-12-08 19:25:05 +00:00
Add IsLowercase and IsUppercase types (#1141)
Co-authored-by: Som Shekhar Mukherjee <iamssmkhrj@gmail.com>
This commit is contained in:
parent
484e030ab9
commit
afe132c4b4
2
index.d.ts
vendored
2
index.d.ts
vendored
@ -147,6 +147,8 @@ export type {NonEmptyTuple} from './source/non-empty-tuple.d.ts';
|
||||
export type {FindGlobalInstanceType, FindGlobalType} from './source/find-global-type.d.ts';
|
||||
export type {If} from './source/if.d.ts';
|
||||
export type {IsUnion} from './source/is-union.d.ts';
|
||||
export type {IsLowercase} from './source/is-lowercase.d.ts';
|
||||
export type {IsUppercase} from './source/is-uppercase.d.ts';
|
||||
|
||||
// Template literal types
|
||||
export type {CamelCase} from './source/camel-case.d.ts';
|
||||
|
||||
@ -228,6 +228,8 @@ Click the type names for complete docs.
|
||||
- [`IsNull`](source/is-null.d.ts) - Returns a boolean for whether the given type is `null`.
|
||||
- [`IsTuple`](source/is-tuple.d.ts) - Returns a boolean for whether the given array is a tuple.
|
||||
- [`IsUnion`](source/is-union.d.ts) - Returns a boolean for whether the given type is a union.
|
||||
- [`IsLowercase`](source/is-lowercase.d.ts) - Returns a boolean for whether the given string literal is lowercase.
|
||||
- [`IsUppercase`](source/is-uppercase.d.ts) - Returns a boolean for whether the given string literal is uppercase.
|
||||
|
||||
### JSON
|
||||
|
||||
|
||||
28
source/internal/array.d.ts
vendored
28
source/internal/array.d.ts
vendored
@ -93,3 +93,31 @@ T extends readonly [...infer U] ?
|
||||
Returns whether the given array `T` is readonly.
|
||||
*/
|
||||
export type IsArrayReadonly<T extends UnknownArray> = If<IsNever<T>, false, T extends unknown[] ? false : true>;
|
||||
|
||||
/**
|
||||
Returns a boolean for whether every element in an array type extends another type.
|
||||
|
||||
Note: This type is not designed to be used with non-tuple arrays (like `number[]`), tuples with optional elements (like `[1?, 2?, 3?]`), or tuples that contain a rest element (like `[1, 2, ...number[]]`).
|
||||
|
||||
@example
|
||||
```
|
||||
import type {Every} from 'type-fest';
|
||||
|
||||
type A = Every<[1, 2, 3], number>;
|
||||
//=> true
|
||||
|
||||
type B = Every<[1, 2, '3'], number>;
|
||||
//=> false
|
||||
|
||||
type C = Every<[number, number | string], number>;
|
||||
//=> boolean
|
||||
|
||||
type D = Every<[true, boolean, true], true>;
|
||||
//=> boolean
|
||||
```
|
||||
*/
|
||||
export type Every<TArray extends UnknownArray, Type> = TArray extends readonly [infer First, ...infer Rest]
|
||||
? First extends Type
|
||||
? Every<Rest, Type>
|
||||
: false
|
||||
: true;
|
||||
|
||||
10
source/internal/string.d.ts
vendored
10
source/internal/string.d.ts
vendored
@ -112,16 +112,6 @@ export type StringLength<S extends string> = string extends S
|
||||
? never
|
||||
: StringToArray<S>['length'];
|
||||
|
||||
/**
|
||||
Returns a boolean for whether the string is lowercased.
|
||||
*/
|
||||
export type IsLowerCase<T extends string> = T extends Lowercase<T> ? true : false;
|
||||
|
||||
/**
|
||||
Returns a boolean for whether the string is uppercased.
|
||||
*/
|
||||
export type IsUpperCase<T extends string> = T extends Uppercase<T> ? true : false;
|
||||
|
||||
/**
|
||||
Returns a boolean for whether a string is whitespace.
|
||||
*/
|
||||
|
||||
36
source/is-lowercase.d.ts
vendored
Normal file
36
source/is-lowercase.d.ts
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
import type {Every} from './internal/array.js';
|
||||
|
||||
/**
|
||||
Returns a boolean for whether the given string literal is lowercase.
|
||||
|
||||
@example
|
||||
```
|
||||
import type {IsLowercase} from 'type-fest';
|
||||
|
||||
IsLowercase<'abc'>;
|
||||
//=> true
|
||||
|
||||
IsLowercase<'Abc'>;
|
||||
//=> false
|
||||
|
||||
IsLowercase<string>;
|
||||
//=> boolean
|
||||
```
|
||||
*/
|
||||
export type IsLowercase<S extends string> = Every<_IsLowercase<S>, true>;
|
||||
|
||||
/**
|
||||
Loops through each part in the string and returns a boolean array indicating whether each part is lowercase.
|
||||
*/
|
||||
type _IsLowercase<S extends string, Accumulator extends boolean[] = []> = S extends `${infer First}${infer Rest}`
|
||||
? _IsLowercase<Rest, [...Accumulator, IsLowercaseHelper<First>]>
|
||||
: [...Accumulator, IsLowercaseHelper<S>];
|
||||
|
||||
/**
|
||||
Returns a boolean for whether an individual part of the string is lowercase.
|
||||
*/
|
||||
type IsLowercaseHelper<S extends string> = S extends Lowercase<string>
|
||||
? true
|
||||
: S extends Uppercase<string> | Capitalize<string> | `${string}${Uppercase<string>}${string}`
|
||||
? false
|
||||
: boolean;
|
||||
36
source/is-uppercase.d.ts
vendored
Normal file
36
source/is-uppercase.d.ts
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
import type {Every} from './internal/array.js';
|
||||
|
||||
/**
|
||||
Returns a boolean for whether the given string literal is uppercase.
|
||||
|
||||
@example
|
||||
```
|
||||
import type {IsUppercase} from 'type-fest';
|
||||
|
||||
IsUppercase<'ABC'>;
|
||||
//=> true
|
||||
|
||||
IsUppercase<'Abc'>;
|
||||
//=> false
|
||||
|
||||
IsUppercase<string>;
|
||||
//=> boolean
|
||||
```
|
||||
*/
|
||||
export type IsUppercase<S extends string> = Every<_IsUppercase<S>, true>;
|
||||
|
||||
/**
|
||||
Loops through each part in the string and returns a boolean array indicating whether each part is uppercase.
|
||||
*/
|
||||
type _IsUppercase<S extends string, Accumulator extends boolean[] = []> = S extends `${infer First}${infer Rest}`
|
||||
? _IsUppercase<Rest, [...Accumulator, IsUppercaseHelper<First>]>
|
||||
: [...Accumulator, IsUppercaseHelper<S>];
|
||||
|
||||
/**
|
||||
Returns a boolean for whether an individual part of the string is uppercase.
|
||||
*/
|
||||
type IsUppercaseHelper<S extends string> = S extends Uppercase<string>
|
||||
? true
|
||||
: S extends Lowercase<string> | Uncapitalize<string> | `${string}${Lowercase<string>}${string}`
|
||||
? false
|
||||
: boolean;
|
||||
8
source/words.d.ts
vendored
8
source/words.d.ts
vendored
@ -1,10 +1,10 @@
|
||||
import type {
|
||||
ApplyDefaultOptions,
|
||||
IsLowerCase,
|
||||
IsNumeric,
|
||||
IsUpperCase,
|
||||
WordSeparators,
|
||||
} from './internal/index.d.ts';
|
||||
import type {IsLowercase} from './is-lowercase.d.ts';
|
||||
import type {IsUppercase} from './is-uppercase.d.ts';
|
||||
|
||||
type SkipEmptyWord<Word extends string> = Word extends '' ? [] : [Word];
|
||||
|
||||
@ -108,10 +108,10 @@ type WordsImplementation<
|
||||
: [true, true] extends [IsNumeric<LastCharacter>, IsNumeric<FirstCharacter>]
|
||||
? WordsImplementation<RemainingCharacters, Options, FirstCharacter, `${CurrentWord}${FirstCharacter}`>
|
||||
// Case change: lower to upper, push word
|
||||
: [true, true] extends [IsLowerCase<LastCharacter>, IsUpperCase<FirstCharacter>]
|
||||
: [true, true] extends [IsLowercase<LastCharacter>, IsUppercase<FirstCharacter>]
|
||||
? [...SkipEmptyWord<CurrentWord>, ...WordsImplementation<RemainingCharacters, Options, FirstCharacter, FirstCharacter>]
|
||||
// Case change: upper to lower, brings back the last character, push word
|
||||
: [true, true] extends [IsUpperCase<LastCharacter>, IsLowerCase<FirstCharacter>]
|
||||
: [true, true] extends [IsUppercase<LastCharacter>, IsLowercase<FirstCharacter>]
|
||||
? [...RemoveLastCharacter<CurrentWord, LastCharacter>, ...WordsImplementation<RemainingCharacters, Options, FirstCharacter, `${LastCharacter}${FirstCharacter}`>]
|
||||
// No case change: concat word
|
||||
: WordsImplementation<RemainingCharacters, Options, FirstCharacter, `${CurrentWord}${FirstCharacter}`>
|
||||
|
||||
31
test-d/internal/every.ts
Normal file
31
test-d/internal/every.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import {expectType} from 'tsd';
|
||||
import type {Every} from '../../source/internal/array.js';
|
||||
|
||||
expectType<Every<[], number>>(true);
|
||||
expectType<Every<[1, 2, 3], number>>(true);
|
||||
expectType<Every<[1, 2, 3], number | bigint>>(true);
|
||||
expectType<Every<[true, false, true, false, boolean], boolean>>(true);
|
||||
expectType<Every<[string, '1', '2', `${number}`], string>>(true);
|
||||
|
||||
expectType<Every<[1, 2, '3'], number>>(false);
|
||||
expectType<Every<['1', 2, 3], number>>(false);
|
||||
expectType<Every<['1', '2', '3', 4, '5'], string>>(false);
|
||||
|
||||
// Union type elements
|
||||
expectType<Every<[string, string | number], string>>({} as boolean);
|
||||
expectType<Every<[true, true, true, boolean], true>>({} as boolean);
|
||||
expectType<Every<[false, false, boolean, false], false>>({} as boolean);
|
||||
expectType<Every<['1', '2', number | bigint, '3'], string>>(false);
|
||||
expectType<Every<[1, 2, number | bigint, 3], number | bigint>>(true);
|
||||
|
||||
// Readonly arrays
|
||||
expectType<Every<readonly [], number>>(true);
|
||||
expectType<Every<readonly [1, 2, 3], number>>(true);
|
||||
expectType<Every<readonly [1, 2, '3'], number>>(false);
|
||||
|
||||
// Unions
|
||||
expectType<Every<[1, 2, 3] | [4, 5, 6], number>>(true); // Both `true`
|
||||
expectType<Every<[1, 2, '3'] | [4, 5, '6'], number>>(false); // Both `false`
|
||||
expectType<Every<[1, 2, 3] | ['1', '2', 3], number>>({} as boolean); // One `true`, one `false`
|
||||
expectType<Every<[true, true] | [true, boolean], true>>({} as boolean); // One `true`, one `boolean`
|
||||
expectType<Every<[true, false] | [true, boolean], true>>({} as boolean); // One `false`, one `boolean`
|
||||
56
test-d/is-lowercase.ts
Normal file
56
test-d/is-lowercase.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import {expectType} from 'tsd';
|
||||
import type {IsLowercase} from '../index.d.ts';
|
||||
|
||||
// Literals
|
||||
expectType<IsLowercase<'abc'>>(true);
|
||||
expectType<IsLowercase<''>>(true);
|
||||
expectType<IsLowercase<'123'>>(true);
|
||||
expectType<IsLowercase<'!@#'>>(true);
|
||||
|
||||
expectType<IsLowercase<'Abc'>>(false);
|
||||
expectType<IsLowercase<'ABC'>>(false);
|
||||
|
||||
// Non-literals
|
||||
expectType<IsLowercase<Lowercase<string>>>(true);
|
||||
expectType<IsLowercase<Lowercase<`on${string}`>>>(true);
|
||||
|
||||
expectType<IsLowercase<Uppercase<string>>>(false);
|
||||
expectType<IsLowercase<Capitalize<`on${string}`>>>(false);
|
||||
expectType<IsLowercase<`on${Capitalize<string>}`>>(false);
|
||||
expectType<IsLowercase<Capitalize<`${string}end`>>>(false);
|
||||
|
||||
expectType<IsLowercase<string>>({} as boolean);
|
||||
expectType<IsLowercase<`on${string}`>>({} as boolean);
|
||||
expectType<IsLowercase<Uncapitalize<string>>>({} as boolean);
|
||||
expectType<IsLowercase<Uncapitalize<`on${string}`>>>({} as boolean);
|
||||
expectType<IsLowercase<`on${Uncapitalize<string>}`>>({} as boolean);
|
||||
expectType<IsLowercase<`${number}`>>({} as boolean);
|
||||
|
||||
expectType<IsLowercase<`Start${string}`>>(false);
|
||||
expectType<IsLowercase<`${string}End`>>(false);
|
||||
expectType<IsLowercase<`${string}Mid${string}`>>(false);
|
||||
|
||||
// Complex non-literals
|
||||
expectType<IsLowercase<`${Lowercase<string>}${Lowercase<string>}`>>(true);
|
||||
|
||||
expectType<IsLowercase<`${Uppercase<string>}${Lowercase<string>}`>>(false);
|
||||
expectType<IsLowercase<`${Lowercase<string>}${Uppercase<string>}`>>(false);
|
||||
expectType<IsLowercase<`${Lowercase<string>}${Uppercase<string>}${Lowercase<string>}`>>(false);
|
||||
expectType<IsLowercase<`${Capitalize<string>}${Lowercase<string>}`>>(false);
|
||||
expectType<IsLowercase<`${Lowercase<string>}${Capitalize<string>}`>>(false);
|
||||
expectType<IsLowercase<`${string}${Capitalize<string>}`>>(false);
|
||||
expectType<IsLowercase<`${number}${Capitalize<string>}`>>(false);
|
||||
|
||||
expectType<IsLowercase<`${string}${Lowercase<string>}`>>({} as boolean);
|
||||
expectType<IsLowercase<`${string}${string}`>>({} as boolean);
|
||||
expectType<IsLowercase<`${Lowercase<string>}${Lowercase<string>}${string}`>>({} as boolean);
|
||||
expectType<IsLowercase<`${string}${Uncapitalize<string>}`>>({} as boolean);
|
||||
expectType<IsLowercase<`${number}/${number}`>>({} as boolean);
|
||||
expectType<IsLowercase<`${string}${number}`>>({} as boolean);
|
||||
|
||||
// Unions
|
||||
expectType<IsLowercase<'abc' | 'xyz'>>(true); // Both `true`
|
||||
expectType<IsLowercase<'abC' | 'xYz'>>(false); // Both `false`
|
||||
expectType<IsLowercase<'abc' | 'Abc'>>({} as boolean); // One `true`, one `false`
|
||||
expectType<IsLowercase<'abc' | `${Uncapitalize<string>}end`>>({} as boolean); // One `true`, one `boolean`
|
||||
expectType<IsLowercase<'xYz' | `abc${string}`>>({} as boolean); // One `false`, one `boolean`
|
||||
56
test-d/is-uppercase.ts
Normal file
56
test-d/is-uppercase.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import {expectType} from 'tsd';
|
||||
import type {IsUppercase} from '../index.d.ts';
|
||||
|
||||
// Literals
|
||||
expectType<IsUppercase<'ABC'>>(true);
|
||||
expectType<IsUppercase<''>>(true);
|
||||
expectType<IsUppercase<'123'>>(true);
|
||||
expectType<IsUppercase<'!@#'>>(true);
|
||||
|
||||
expectType<IsUppercase<'Abc'>>(false);
|
||||
expectType<IsUppercase<'abc'>>(false);
|
||||
|
||||
// Non-literals
|
||||
expectType<IsUppercase<Uppercase<string>>>(true);
|
||||
expectType<IsUppercase<Uppercase<`on${string}`>>>(true);
|
||||
|
||||
expectType<IsUppercase<Lowercase<string>>>(false);
|
||||
expectType<IsUppercase<Uncapitalize<`ON${string}`>>>(false);
|
||||
expectType<IsUppercase<`ON${Uncapitalize<string>}`>>(false);
|
||||
expectType<IsUppercase<Uncapitalize<`${string}END`>>>(false);
|
||||
|
||||
expectType<IsUppercase<string>>({} as boolean);
|
||||
expectType<IsUppercase<`ON${string}`>>({} as boolean);
|
||||
expectType<IsUppercase<Capitalize<string>>>({} as boolean);
|
||||
expectType<IsUppercase<Capitalize<`ON${string}`>>>({} as boolean);
|
||||
expectType<IsUppercase<`ON${Capitalize<string>}`>>({} as boolean);
|
||||
expectType<IsUppercase<`${number}`>>({} as boolean);
|
||||
|
||||
expectType<IsUppercase<`sTART${string}`>>(false);
|
||||
expectType<IsUppercase<`${string}eND`>>(false);
|
||||
expectType<IsUppercase<`${string}mID${string}`>>(false);
|
||||
|
||||
// Complex non-literals
|
||||
expectType<IsUppercase<`${Uppercase<string>}${Uppercase<string>}`>>(true);
|
||||
|
||||
expectType<IsUppercase<`${Lowercase<string>}${Uppercase<string>}`>>(false);
|
||||
expectType<IsUppercase<`${Uppercase<string>}${Lowercase<string>}`>>(false);
|
||||
expectType<IsUppercase<`${Uppercase<string>}${Lowercase<string>}${Uppercase<string>}`>>(false);
|
||||
expectType<IsUppercase<`${Uncapitalize<string>}${Uppercase<string>}`>>(false);
|
||||
expectType<IsUppercase<`${Uppercase<string>}${Uncapitalize<string>}`>>(false);
|
||||
expectType<IsUppercase<`${string}${Uncapitalize<string>}`>>(false);
|
||||
expectType<IsUppercase<`${number}${Uncapitalize<string>}`>>(false);
|
||||
|
||||
expectType<IsUppercase<`${string}${Uppercase<string>}`>>({} as boolean);
|
||||
expectType<IsUppercase<`${string}${string}`>>({} as boolean);
|
||||
expectType<IsUppercase<`${Uppercase<string>}${Uppercase<string>}${string}`>>({} as boolean);
|
||||
expectType<IsUppercase<`${string}${Capitalize<string>}`>>({} as boolean);
|
||||
expectType<IsUppercase<`${number}/${number}`>>({} as boolean);
|
||||
expectType<IsUppercase<`${string}${number}`>>({} as boolean);
|
||||
|
||||
// Unions
|
||||
expectType<IsUppercase<'ABC' | 'XYZ'>>(true); // Both `true`
|
||||
expectType<IsUppercase<'ABc' | 'XyZ'>>(false); // Both `false`
|
||||
expectType<IsUppercase<'ABC' | 'aBC'>>({} as boolean); // One `true`, one `false`
|
||||
expectType<IsUppercase<'ABC' | `${Capitalize<string>}END`>>({} as boolean); // One `true`, one `boolean`
|
||||
expectType<IsUppercase<'XyZ' | `ABC${string}`>>({} as boolean); // One `false`, one `boolean`
|
||||
Loading…
x
Reference in New Issue
Block a user