@depup/type-fest 5.5.0-depup.0 → 5.10.0-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/changes.json +1 -1
- package/index.d.ts +17 -8
- package/package.json +9 -6
- package/readme.md +75 -61
- package/source/absolute.d.ts +52 -0
- package/source/all-extend.d.ts +9 -5
- package/source/all-union-fields.d.ts +18 -18
- package/source/and.d.ts +1 -1
- package/source/array-reverse.d.ts +17 -15
- package/source/array-splice.d.ts +24 -24
- package/source/array-tail.d.ts +7 -7
- package/source/camel-case.d.ts +38 -5
- package/source/camel-cased-properties-deep.d.ts +11 -4
- package/source/camel-cased-properties.d.ts +5 -1
- package/source/conditional-keys.d.ts +1 -1
- package/source/delimiter-case.d.ts +11 -9
- package/source/delimiter-cased-properties-deep.d.ts +8 -1
- package/source/delimiter-cased-properties.d.ts +5 -1
- package/source/empty-object.d.ts +1 -1
- package/source/entries.d.ts +1 -1
- package/source/entry.d.ts +1 -1
- package/source/exclude-exactly.d.ts +11 -11
- package/source/exclude-rest-element.d.ts +4 -4
- package/source/exclusify-union.d.ts +4 -4
- package/source/extends-strict.d.ts +129 -22
- package/source/extract-exactly.d.ts +56 -0
- package/source/get.d.ts +1 -1
- package/source/greater-than.d.ts +3 -2
- package/source/has-optional-keys.d.ts +1 -1
- package/source/has-readonly-keys.d.ts +1 -1
- package/source/has-required-keys.d.ts +1 -1
- package/source/has-writable-keys.d.ts +1 -1
- package/source/int-closed-range.d.ts +5 -4
- package/source/int-range.d.ts +57 -12
- package/source/internal/array.d.ts +22 -21
- package/source/internal/keys.d.ts +9 -9
- package/source/internal/numeric.d.ts +19 -65
- package/source/internal/object.d.ts +44 -6
- package/source/internal/string.d.ts +1 -76
- package/source/internal/tuple.d.ts +2 -2
- package/source/internal/type.d.ts +16 -10
- package/source/is-boolean-literal.d.ts +39 -0
- package/source/is-integer.d.ts +8 -8
- package/source/is-literal.d.ts +43 -267
- package/source/is-numeric-literal.d.ts +50 -0
- package/source/is-string-literal.d.ts +72 -0
- package/source/is-symbol-literal.d.ts +39 -0
- package/source/is-tuple.d.ts +3 -3
- package/source/is-union.d.ts +12 -12
- package/source/iterable-element.d.ts +5 -5
- package/source/jsonify.d.ts +5 -9
- package/source/kebab-case.d.ts +1 -0
- package/source/kebab-cased-properties-deep.d.ts +7 -0
- package/source/kebab-cased-properties.d.ts +5 -1
- package/source/keys-of-union.d.ts +2 -2
- package/source/last-array-element.d.ts +66 -13
- package/source/less-than-or-equal.d.ts +1 -1
- package/source/literal-to-primitive.d.ts +1 -1
- package/source/literal-union.d.ts +1 -1
- package/source/merge-deep.d.ts +3 -3
- package/source/merge-exclusive.d.ts +3 -3
- package/source/multidimensional-array.d.ts +1 -1
- package/source/multidimensional-readonly-array.d.ts +1 -1
- package/source/non-nullable-deep.d.ts +102 -0
- package/source/numeric.d.ts +3 -3
- package/source/object-merge.d.ts +21 -16
- package/source/omit-deep.d.ts +22 -22
- package/source/or.d.ts +1 -1
- package/source/package-json.d.ts +7 -7
- package/source/partial-deep.d.ts +3 -1
- package/source/pascal-case.d.ts +1 -0
- package/source/pascal-cased-properties-deep.d.ts +7 -0
- package/source/pascal-cased-properties.d.ts +5 -1
- package/source/pick-deep.d.ts +2 -0
- package/source/readonly-deep.d.ts +5 -3
- package/source/remove-prefix.d.ts +16 -34
- package/source/remove-suffix.d.ts +114 -0
- package/source/rename-keys.d.ts +163 -0
- package/source/replace.d.ts +2 -2
- package/source/require-all-or-none.d.ts +5 -5
- package/source/require-at-least-one.d.ts +9 -11
- package/source/require-exactly-one.d.ts +7 -7
- package/source/require-one-or-none.d.ts +5 -5
- package/source/required-deep.d.ts +3 -1
- package/source/schema.d.ts +16 -8
- package/source/screaming-snake-case.d.ts +1 -0
- package/source/set-non-nullable-deep.d.ts +8 -4
- package/source/set-non-nullable.d.ts +1 -1
- package/source/set-optional.d.ts +5 -5
- package/source/set-readonly.d.ts +3 -3
- package/source/set-required-deep.d.ts +3 -2
- package/source/set-required.d.ts +13 -12
- package/source/shared-union-fields-deep.d.ts +6 -4
- package/source/shared-union-fields.d.ts +9 -9
- package/source/snake-case.d.ts +1 -0
- package/source/snake-cased-properties-deep.d.ts +7 -0
- package/source/snake-cased-properties.d.ts +5 -1
- package/source/some-extend.d.ts +9 -5
- package/source/split-on-rest-element.d.ts +20 -17
- package/source/split.d.ts +22 -11
- package/source/string-length.d.ts +38 -0
- package/source/string-repeat.d.ts +48 -21
- package/source/string-slice.d.ts +1 -1
- package/source/string-to-array.d.ts +97 -0
- package/source/string-to-number.d.ts +67 -0
- package/source/subtract.d.ts +4 -3
- package/source/sum.d.ts +5 -4
- package/source/tagged.d.ts +3 -5
- package/source/tsconfig-json.d.ts +40 -8
- package/source/tuple-of.d.ts +42 -8
- package/source/typed-array.d.ts +6 -0
- package/source/union-length.d.ts +27 -0
- package/source/union-max.d.ts +56 -0
- package/source/union-to-intersection.d.ts +1 -1
- package/source/union-to-tuple.d.ts +8 -4
- package/source/unwrap-required.d.ts +37 -0
- package/source/words.d.ts +30 -4
- package/source/writable.d.ts +14 -14
- package/source/xor.d.ts +1 -1
package/source/omit-deep.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ It supports removing specific items from an array, replacing each removed item w
|
|
|
17
17
|
|
|
18
18
|
Use-case: Remove unneeded parts of complex objects.
|
|
19
19
|
|
|
20
|
-
Use [`Omit
|
|
20
|
+
Use [`Omit<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys) if you only need one level deep.
|
|
21
21
|
|
|
22
22
|
@example
|
|
23
23
|
```
|
|
@@ -93,34 +93,34 @@ type OmitDeepHelper<T, PathTuple extends UnknownArray> =
|
|
|
93
93
|
Omit one path from the given object/array.
|
|
94
94
|
*/
|
|
95
95
|
type OmitDeepWithOnePath<T, Path extends string | number> =
|
|
96
|
-
T extends NonRecursiveType
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
T extends NonRecursiveType
|
|
97
|
+
? T
|
|
98
|
+
: T extends UnknownArray ? SetArrayAccess<OmitDeepArrayWithOnePath<T, Path>, IsArrayReadonly<T>>
|
|
99
|
+
: T extends object ? OmitDeepObjectWithOnePath<T, Path>
|
|
100
|
+
: T;
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
103
|
Omit one path from the given object.
|
|
104
104
|
*/
|
|
105
105
|
type OmitDeepObjectWithOnePath<ObjectT extends object, P extends string | number> =
|
|
106
|
-
P extends `${infer RecordKeyInPath}.${infer SubPath}`
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
106
|
+
P extends `${infer RecordKeyInPath}.${infer SubPath}`
|
|
107
|
+
? {
|
|
108
|
+
[Key in keyof ObjectT]:
|
|
109
|
+
IsEqual<RecordKeyInPath, ToString<Key>> extends true
|
|
110
|
+
? ExactKey<ObjectT, Key> extends infer RealKey
|
|
111
|
+
? RealKey extends keyof ObjectT
|
|
112
|
+
? OmitDeepWithOnePath<ObjectT[RealKey], SubPath>
|
|
113
|
+
: ObjectT[Key]
|
|
113
114
|
: ObjectT[Key]
|
|
114
115
|
: ObjectT[Key]
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
: ObjectT;
|
|
116
|
+
}
|
|
117
|
+
: ExactKey<ObjectT, P> extends infer Key
|
|
118
|
+
? IsNever<Key> extends true
|
|
119
|
+
? ObjectT
|
|
120
|
+
: Key extends PropertyKey
|
|
121
|
+
? Omit<ObjectT, Key>
|
|
122
|
+
: ObjectT
|
|
123
|
+
: ObjectT;
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
126
|
Omit one path from from the given array.
|
package/source/or.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {OrAll} from './or-all.d.ts';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
Returns a boolean for whether either of two given types is true
|
|
4
|
+
Returns a boolean for whether either of two given types is `true`.
|
|
5
5
|
|
|
6
6
|
Use-case: Constructing complex conditional types where at least one condition must be satisfied.
|
|
7
7
|
|
package/source/package-json.d.ts
CHANGED
|
@@ -699,12 +699,12 @@ Type for [npm's `package.json` file](https://docs.npmjs.com/creating-a-package-j
|
|
|
699
699
|
@category File
|
|
700
700
|
*/
|
|
701
701
|
export type PackageJson =
|
|
702
|
-
JsonObject
|
|
703
|
-
PackageJson.NodeJsStandard
|
|
704
|
-
PackageJson.PackageJsonStandard
|
|
705
|
-
PackageJson.NonStandardEntryPoints
|
|
706
|
-
PackageJson.TypeScriptConfiguration
|
|
707
|
-
PackageJson.YarnConfiguration
|
|
708
|
-
PackageJson.JSPMConfiguration;
|
|
702
|
+
JsonObject
|
|
703
|
+
& PackageJson.NodeJsStandard
|
|
704
|
+
& PackageJson.PackageJsonStandard
|
|
705
|
+
& PackageJson.NonStandardEntryPoints
|
|
706
|
+
& PackageJson.TypeScriptConfiguration
|
|
707
|
+
& PackageJson.YarnConfiguration
|
|
708
|
+
& PackageJson.JSPMConfiguration;
|
|
709
709
|
|
|
710
710
|
export {};
|
package/source/partial-deep.d.ts
CHANGED
|
@@ -44,12 +44,14 @@ type DefaultPartialDeepOptions = {
|
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
Create a
|
|
47
|
+
Create a deeply optional version of another type.
|
|
48
48
|
|
|
49
49
|
Use-cases:
|
|
50
50
|
- Merging a default settings/config object with another object, the second object would be a deep partial of the default object.
|
|
51
51
|
- Mocking and testing complex entities, where populating an entire object with its keys would be redundant in terms of the mock or test.
|
|
52
52
|
|
|
53
|
+
Use [`Partial<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype) if you only need one level deep.
|
|
54
|
+
|
|
53
55
|
@example
|
|
54
56
|
```
|
|
55
57
|
import type {PartialDeep} from 'type-fest';
|
package/source/pascal-case.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type {PascalCase} from 'type-fest';
|
|
|
12
12
|
|
|
13
13
|
const someVariable: PascalCase<'foo-bar'> = 'FooBar';
|
|
14
14
|
const preserveConsecutiveUppercase: PascalCase<'foo-BAR-baz', {preserveConsecutiveUppercase: true}> = 'FooBARBaz';
|
|
15
|
+
const splitOnPunctuation: PascalCase<'foo-bar>>baz', {splitOnPunctuation: true}> = 'FooBarBaz';
|
|
15
16
|
|
|
16
17
|
// Advanced
|
|
17
18
|
|
|
@@ -48,6 +48,13 @@ const preserveConsecutiveUppercase: PascalCasedPropertiesDeep<{fooBAR: {fooBARBi
|
|
|
48
48
|
}],
|
|
49
49
|
},
|
|
50
50
|
};
|
|
51
|
+
|
|
52
|
+
const splitOnPunctuation: PascalCasedPropertiesDeep<{'user@info': {'user::id': number; 'user::name': string}}, {splitOnPunctuation: true}> = {
|
|
53
|
+
UserInfo: {
|
|
54
|
+
UserId: 1,
|
|
55
|
+
UserName: 'Tom',
|
|
56
|
+
},
|
|
57
|
+
};
|
|
51
58
|
```
|
|
52
59
|
|
|
53
60
|
@category Change case
|
|
@@ -3,7 +3,7 @@ import type {ApplyDefaultOptions} from './internal/index.d.ts';
|
|
|
3
3
|
import type {PascalCase} from './pascal-case.d.ts';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
Convert object properties to pascal case
|
|
6
|
+
Convert top-level object properties to pascal case.
|
|
7
7
|
|
|
8
8
|
This can be useful when, for example, converting some API types from a different style.
|
|
9
9
|
|
|
@@ -27,6 +27,10 @@ const result: PascalCasedProperties<User> = {
|
|
|
27
27
|
const preserveConsecutiveUppercase: PascalCasedProperties<{fooBAR: string}, {preserveConsecutiveUppercase: true}> = {
|
|
28
28
|
FooBAR: 'string',
|
|
29
29
|
};
|
|
30
|
+
|
|
31
|
+
const splitOnPunctuation: PascalCasedProperties<{'foo::bar': string}, {splitOnPunctuation: true}> = {
|
|
32
|
+
FooBar: 'string',
|
|
33
|
+
};
|
|
30
34
|
```
|
|
31
35
|
|
|
32
36
|
@category Change case
|
package/source/pick-deep.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ It supports recursing into arrays.
|
|
|
14
14
|
|
|
15
15
|
Use-case: Distill complex objects down to the components you need to target.
|
|
16
16
|
|
|
17
|
+
Use [`Pick<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys) if you only need one level deep.
|
|
18
|
+
|
|
17
19
|
@example
|
|
18
20
|
```
|
|
19
21
|
import type {PickDeep, PartialDeep} from 'type-fest';
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type {BuiltIns, HasMultipleCallSignatures} from './internal/index.d.ts';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
|
|
4
|
+
Create a deeply immutable version of another type.
|
|
5
5
|
|
|
6
6
|
This is useful when a deeply nested structure needs to be exposed as completely immutable, for example, an imported JSON module or when receiving an API response that is passed around.
|
|
7
7
|
|
|
8
8
|
Please upvote [this issue](https://github.com/microsoft/TypeScript/issues/13923) if you want to have this type as a built-in in TypeScript.
|
|
9
9
|
|
|
10
|
+
Use [`Readonly<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype) if you only need one level deep.
|
|
11
|
+
|
|
10
12
|
@example
|
|
11
13
|
```
|
|
12
14
|
import type {ReadonlyDeep} from 'type-fest';
|
|
@@ -83,8 +85,8 @@ export type ReadonlyDeep<T> = T extends BuiltIns
|
|
|
83
85
|
? ReadonlyMapDeep<KeyType, ValueType>
|
|
84
86
|
: T extends Readonly<ReadonlySet<infer ItemType>>
|
|
85
87
|
? ReadonlySetDeep<ItemType>
|
|
86
|
-
|
|
87
|
-
T extends readonly [] | readonly [...never[]]
|
|
88
|
+
// Identify tuples to avoid converting them to arrays inadvertently; special case `readonly [...never[]]`, as it emerges undesirably from recursive invocations of ReadonlyDeep below.
|
|
89
|
+
: T extends readonly [] | readonly [...never[]]
|
|
88
90
|
? readonly []
|
|
89
91
|
: T extends readonly [infer U, ...infer V]
|
|
90
92
|
? readonly [ReadonlyDeep<U>, ...ReadonlyDeep<V>]
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type {ApplyDefaultOptions} from './internal/object.d.ts';
|
|
2
2
|
import type {IfNotAnyOrNever, Not} from './internal/type.d.ts';
|
|
3
|
-
import type {IsStringLiteral} from './is-literal.d.ts';
|
|
3
|
+
import type {IsStringLiteral} from './is-string-literal.d.ts';
|
|
4
|
+
import type {IsNever} from './is-never.d.ts';
|
|
4
5
|
import type {Or} from './or.d.ts';
|
|
6
|
+
import type {If} from './if.d.ts';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
@see {@link RemovePrefix}
|
|
@@ -58,24 +60,6 @@ export type RemovePrefixOptions = {
|
|
|
58
60
|
type D = RemovePrefix<`id-${number}`, 'id-', {strict: false}>;
|
|
59
61
|
//=> `${number}`
|
|
60
62
|
```
|
|
61
|
-
|
|
62
|
-
Note: If it can be statically determined that the input string can never start with the specified non-literal prefix, then the input string is returned as-is, regardless of the value of this option.
|
|
63
|
-
For example, ``RemovePrefix<`${string}/${number}`, `${string}:`>`` returns `` `${string}/${number}` ``, since a string of type `` `${string}/${number}` `` can never start with a prefix of type `` `${string}:` ``.
|
|
64
|
-
```
|
|
65
|
-
import type {RemovePrefix} from 'type-fest';
|
|
66
|
-
|
|
67
|
-
type A = RemovePrefix<`${string}/${number}`, `${string}:`, {strict: true}>;
|
|
68
|
-
//=> `${string}/${number}`
|
|
69
|
-
|
|
70
|
-
type B = RemovePrefix<`${string}/${number}`, `${string}:`, {strict: false}>;
|
|
71
|
-
//=> `${string}/${number}`
|
|
72
|
-
|
|
73
|
-
type C = RemovePrefix<'on-change', `${number}-`, {strict: true}>;
|
|
74
|
-
//=> 'on-change'
|
|
75
|
-
|
|
76
|
-
type D = RemovePrefix<'on-change', `${number}-`, {strict: false}>;
|
|
77
|
-
//=> 'on-change'
|
|
78
|
-
```
|
|
79
63
|
*/
|
|
80
64
|
strict?: boolean;
|
|
81
65
|
};
|
|
@@ -110,23 +94,21 @@ type D = RemovePrefix<`handle${Capitalize<string>}`, 'handle'>;
|
|
|
110
94
|
@category Template literal
|
|
111
95
|
*/
|
|
112
96
|
export type RemovePrefix<S extends string, Prefix extends string, Options extends RemovePrefixOptions = {}> =
|
|
113
|
-
IfNotAnyOrNever<
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
>
|
|
121
|
-
>;
|
|
97
|
+
IfNotAnyOrNever<S, {
|
|
98
|
+
ifNot: If<
|
|
99
|
+
IsNever<Prefix>,
|
|
100
|
+
S,
|
|
101
|
+
_RemovePrefix<S, Prefix, ApplyDefaultOptions<RemovePrefixOptions, DefaultRemovePrefixOptions, Options>>
|
|
102
|
+
>;
|
|
103
|
+
}>;
|
|
122
104
|
|
|
123
105
|
type _RemovePrefix<S extends string, Prefix extends string, Options extends Required<RemovePrefixOptions>> =
|
|
124
|
-
Prefix extends string // For distributing `Prefix`
|
|
125
|
-
? S extends `${Prefix}${infer Rest}`
|
|
106
|
+
Prefix extends string // For distributing `Prefix`
|
|
126
107
|
? Or<IsStringLiteral<Prefix>, Not<Options['strict']>> extends true
|
|
127
|
-
? Rest
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
108
|
+
? S extends `${Prefix}${infer Rest}`
|
|
109
|
+
? Rest
|
|
110
|
+
: S // Return back `S` when `Prefix` is not present at the start of `S`
|
|
111
|
+
: string // Fallback to `string` when `Prefix` is non-literal and `strict` is enabled
|
|
112
|
+
: never;
|
|
131
113
|
|
|
132
114
|
export {};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type {ApplyDefaultOptions} from './internal/object.d.ts';
|
|
2
|
+
import type {IfNotAnyOrNever, Not} from './internal/type.d.ts';
|
|
3
|
+
import type {IsStringLiteral} from './is-string-literal.d.ts';
|
|
4
|
+
import type {IsNever} from './is-never.d.ts';
|
|
5
|
+
import type {Or} from './or.d.ts';
|
|
6
|
+
import type {If} from './if.d.ts';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
@see {@link RemoveSuffix}
|
|
10
|
+
*/
|
|
11
|
+
export type RemoveSuffixOptions = {
|
|
12
|
+
/**
|
|
13
|
+
When enabled, instantiations with non-literal suffixes (e.g., `string`, `Uppercase<string>`, `` `.${string}` ``) simply return `string`, since their precise structure cannot be statically determined.
|
|
14
|
+
|
|
15
|
+
Note: Disabling this option can produce misleading results that might not reflect the actual runtime behavior.
|
|
16
|
+
For example, ``RemoveSuffix<'report.pdf', `.${string}`, {strict: false}>`` returns `'report'`, but at runtime, suffix could be `'.txt'` (which satisfies `` `.${string}` ``) and removing `'.txt'` from `'report.pdf'` would not result in `'report'`.
|
|
17
|
+
|
|
18
|
+
So, it is recommended to not disable this option unless you are aware of the implications.
|
|
19
|
+
|
|
20
|
+
@default true
|
|
21
|
+
|
|
22
|
+
@example
|
|
23
|
+
```
|
|
24
|
+
import type {RemoveSuffix} from 'type-fest';
|
|
25
|
+
|
|
26
|
+
type A = RemoveSuffix<'report.pdf', `.${string}`, {strict: true}>;
|
|
27
|
+
//=> string
|
|
28
|
+
|
|
29
|
+
type B = RemoveSuffix<'report.pdf', `.${string}`, {strict: false}>;
|
|
30
|
+
//=> 'report'
|
|
31
|
+
|
|
32
|
+
type C = RemoveSuffix<'on-change', string, {strict: true}>;
|
|
33
|
+
//=> string
|
|
34
|
+
|
|
35
|
+
type D = RemoveSuffix<'on-change', string, {strict: false}>;
|
|
36
|
+
//=> 'o'
|
|
37
|
+
|
|
38
|
+
type E = RemoveSuffix<`${number}/${string}`, `/${string}`, {strict: true}>;
|
|
39
|
+
//=> string
|
|
40
|
+
|
|
41
|
+
type F = RemoveSuffix<`${number}/${string}`, `/${string}`, {strict: false}>;
|
|
42
|
+
//=> `${number}`
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Note: This option has no effect when only the input string type is non-literal. For example, ``RemoveSuffix<`${string}.pdf`, '.pdf'>`` will always return `string`.
|
|
46
|
+
|
|
47
|
+
@example
|
|
48
|
+
```
|
|
49
|
+
import type {RemoveSuffix} from 'type-fest';
|
|
50
|
+
|
|
51
|
+
type A = RemoveSuffix<`${string}.pdf`, '.pdf', {strict: true}>;
|
|
52
|
+
//=> string
|
|
53
|
+
|
|
54
|
+
type B = RemoveSuffix<`${string}.pdf`, '.pdf', {strict: false}>;
|
|
55
|
+
//=> string
|
|
56
|
+
|
|
57
|
+
type C = RemoveSuffix<`${number}px`, 'px', {strict: true}>;
|
|
58
|
+
//=> `${number}`
|
|
59
|
+
|
|
60
|
+
type D = RemoveSuffix<`${number}px`, 'px', {strict: false}>;
|
|
61
|
+
//=> `${number}`
|
|
62
|
+
```
|
|
63
|
+
*/
|
|
64
|
+
strict?: boolean;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
type DefaultRemoveSuffixOptions = {
|
|
68
|
+
strict: true;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
Remove the specified suffix from the end of a string.
|
|
73
|
+
|
|
74
|
+
@example
|
|
75
|
+
```
|
|
76
|
+
import type {RemoveSuffix} from 'type-fest';
|
|
77
|
+
|
|
78
|
+
type A = RemoveSuffix<'report.pdf', '.pdf'>;
|
|
79
|
+
//=> 'report'
|
|
80
|
+
|
|
81
|
+
type B = RemoveSuffix<'bg-blue-500' | 'text-green-500' | 'border-slate-500', '-500'>;
|
|
82
|
+
//=> 'bg-blue' | 'border-slate' | 'text-green'
|
|
83
|
+
|
|
84
|
+
type C = RemoveSuffix<'report.pdf', '.txt'>;
|
|
85
|
+
//=> 'report.pdf'
|
|
86
|
+
|
|
87
|
+
type D = RemoveSuffix<`api/${string}/analytics`, '/analytics'>;
|
|
88
|
+
//=> `api/${string}`
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
@see {@link RemoveSuffixOptions}
|
|
92
|
+
|
|
93
|
+
@category String
|
|
94
|
+
@category Template literal
|
|
95
|
+
*/
|
|
96
|
+
export type RemoveSuffix<S extends string, Suffix extends string, Options extends RemoveSuffixOptions = {}> =
|
|
97
|
+
IfNotAnyOrNever<S, {
|
|
98
|
+
ifNot: If<
|
|
99
|
+
IsNever<Suffix>,
|
|
100
|
+
S,
|
|
101
|
+
_RemoveSuffix<S, Suffix, ApplyDefaultOptions<RemoveSuffixOptions, DefaultRemoveSuffixOptions, Options>>
|
|
102
|
+
>;
|
|
103
|
+
}>;
|
|
104
|
+
|
|
105
|
+
type _RemoveSuffix<S extends string, Suffix extends string, Options extends Required<RemoveSuffixOptions>> =
|
|
106
|
+
Suffix extends string // For distributing `Suffix`
|
|
107
|
+
? Or<IsStringLiteral<Suffix>, Not<Options['strict']>> extends true
|
|
108
|
+
? S extends `${infer Rest}${Suffix}`
|
|
109
|
+
? Rest
|
|
110
|
+
: S // Return back `S` when `Suffix` is not present at the end of `S`
|
|
111
|
+
: string // Fallback to `string` when `Suffix` is non-literal and `strict` is enabled
|
|
112
|
+
: never;
|
|
113
|
+
|
|
114
|
+
export {};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import type {IsLiteral} from './is-literal.d.ts';
|
|
2
|
+
import type {ReadonlyKeysOf} from './readonly-keys-of.d.ts';
|
|
3
|
+
import type {RequiredKeysOf} from './required-keys-of.d.ts';
|
|
4
|
+
import type {OptionalKeysOf} from './optional-keys-of.d.ts';
|
|
5
|
+
import type {OmitIndexSignature} from './omit-index-signature.d.ts';
|
|
6
|
+
import type {SetRequired} from './set-required.d.ts';
|
|
7
|
+
import type {SetReadonly} from './set-readonly.d.ts';
|
|
8
|
+
import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled} from './internal/type.d.ts';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
Rename keys in an object type according to a map of old-to-new names.
|
|
12
|
+
|
|
13
|
+
@example
|
|
14
|
+
```
|
|
15
|
+
import type {RenameKeys} from 'type-fest';
|
|
16
|
+
|
|
17
|
+
type User = {
|
|
18
|
+
id: string;
|
|
19
|
+
firstName: string;
|
|
20
|
+
createdAt: Date;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type Renamed = RenameKeys<User, {firstName: 'first_name'; createdAt: 'created_at'}>;
|
|
24
|
+
//=> {id: string; first_name: string; created_at: Date}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
@example
|
|
28
|
+
```
|
|
29
|
+
import type {RenameKeys} from 'type-fest';
|
|
30
|
+
|
|
31
|
+
type SearchInput = {
|
|
32
|
+
textQuery: string;
|
|
33
|
+
voiceQuery: Blob;
|
|
34
|
+
imageQuery: File;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type Normalized = RenameKeys<SearchInput, {textQuery: 'query'; voiceQuery: 'query'; imageQuery: 'query'}>;
|
|
38
|
+
//=> {query: string | Blob | File}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Note: When multiple source keys map to the same target, the target's value type is the union of the contributors' value types. The target is optional only when every contributor is optional, and is `readonly` when any contributor is `readonly`. With `exactOptionalPropertyTypes` disabled, the value type of a mixed-optionality merge also includes `undefined`.
|
|
42
|
+
|
|
43
|
+
@example
|
|
44
|
+
```
|
|
45
|
+
import type {RenameKeys} from 'type-fest';
|
|
46
|
+
|
|
47
|
+
// All colliding keys are required, so the target is required.
|
|
48
|
+
type A = RenameKeys<{a: 1; b: 2}, {a: 'x'; b: 'x'}>;
|
|
49
|
+
//=> {x: 1 | 2}
|
|
50
|
+
|
|
51
|
+
// All colliding keys are optional, so the target is optional.
|
|
52
|
+
type B = RenameKeys<{a?: 1; b?: 2}, {a: 'x'; b: 'x'}>;
|
|
53
|
+
//=> {x?: 1 | 2}
|
|
54
|
+
|
|
55
|
+
// One of the colliding keys is required, so the target is required.
|
|
56
|
+
type C = RenameKeys<{a: 1; b?: 2}, {a: 'x'; b: 'x'}>;
|
|
57
|
+
//=> {x: 1 | 2}
|
|
58
|
+
|
|
59
|
+
// One of the colliding keys is `readonly`, so the target is `readonly`.
|
|
60
|
+
type D = RenameKeys<{readonly a: 1; b: 2}, {a: 'x'; b: 'x'}>;
|
|
61
|
+
//=> {readonly x: 1 | 2}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
@example
|
|
65
|
+
```
|
|
66
|
+
// @exactOptionalPropertyTypes: false
|
|
67
|
+
import type {RenameKeys} from 'type-fest';
|
|
68
|
+
|
|
69
|
+
// With `exactOptionalPropertyTypes` disabled, a mixed-optionality merge includes `undefined`.
|
|
70
|
+
type E = RenameKeys<{a?: 1; b: 2}, {a: 'x'; b: 'x'}>;
|
|
71
|
+
//=> {x: 1 | 2 | undefined}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Note: A union target distributes, producing one output key per member.
|
|
75
|
+
|
|
76
|
+
@example
|
|
77
|
+
```
|
|
78
|
+
import type {RenameKeys} from 'type-fest';
|
|
79
|
+
|
|
80
|
+
type A = RenameKeys<{a: string}, {a: 'b' | 'c'}>;
|
|
81
|
+
//=> {b: string; c: string}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Note: An entry whose value is not a literal `PropertyKey` (such as `string`) is also ignored, leaving that key's name unchanged.
|
|
85
|
+
|
|
86
|
+
@example
|
|
87
|
+
```
|
|
88
|
+
import type {RenameKeys} from 'type-fest';
|
|
89
|
+
|
|
90
|
+
type A = RenameKeys<{a: 1}, {a: string}>;
|
|
91
|
+
//=> {a: 1}
|
|
92
|
+
|
|
93
|
+
type B = RenameKeys<{a: 1; b: 2}, {a: 'x'; b: symbol}>;
|
|
94
|
+
//=> {x: 1; b: 2}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Note: A rename map entry whose key is not a property of the source type is ignored.
|
|
98
|
+
|
|
99
|
+
@example
|
|
100
|
+
```
|
|
101
|
+
import type {RenameKeys} from 'type-fest';
|
|
102
|
+
|
|
103
|
+
type A = RenameKeys<{a: 1; b: 2}, {a: 'x'; c: 'y'}>;
|
|
104
|
+
//=> {x: 1; b: 2}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
@category Object
|
|
108
|
+
*/
|
|
109
|
+
export type RenameKeys<
|
|
110
|
+
BaseType extends object,
|
|
111
|
+
RenameMap extends Record<PropertyKey, PropertyKey>,
|
|
112
|
+
> = IfNotAnyOrNever<BaseType, {
|
|
113
|
+
ifNot: BaseType extends unknown // For distributing `BaseType`
|
|
114
|
+
? RenameMap extends unknown // For distributing `RenameMap`
|
|
115
|
+
? RenameOnce<BaseType, NormalizeMap<RenameMap>>
|
|
116
|
+
: never
|
|
117
|
+
: never;
|
|
118
|
+
}>;
|
|
119
|
+
|
|
120
|
+
type RenameOnce<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>> =
|
|
121
|
+
RestoreMergedUndefined<BaseType, RenameMap,
|
|
122
|
+
ApplyReadonly<BaseType, RenameMap,
|
|
123
|
+
ApplyRequired<BaseType, RenameMap,
|
|
124
|
+
RenameNaive<BaseType, RenameMap>>>>;
|
|
125
|
+
|
|
126
|
+
type RenameNaive<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>> = {
|
|
127
|
+
// Two keys mapping to one target produce a union value and keep only the first key's modifiers.
|
|
128
|
+
// Like for example, `{a?: 1; b: 2}` with `{a: 'x'; b: 'x'}` produces `{x?: 1 | 2}`, taking `a`'s optional.
|
|
129
|
+
[Key in keyof BaseType as TargetOf<Key, RenameMap>]: Required<BaseType>[Key];
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// A merged target kept only one modifier in `RenameNaive`, so re-force these from every contributor.
|
|
133
|
+
type ApplyRequired<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>, Renamed> =
|
|
134
|
+
SetRequired<Renamed, TargetOf<RequiredKeysOf<OmitIndexSignature<BaseType>>, RenameMap> & keyof Renamed>;
|
|
135
|
+
|
|
136
|
+
type ApplyReadonly<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>, Renamed> =
|
|
137
|
+
SetReadonly<Renamed, TargetOf<ReadonlyKeysOf<OmitIndexSignature<BaseType>>, RenameMap> & keyof Renamed>;
|
|
138
|
+
|
|
139
|
+
// `exactOptionalPropertyTypes` off keeps `undefined` on a target that merged a required and an optional source.
|
|
140
|
+
// Source `{a?: 1; x: 2}` with `{a: 'x'}` gives `{x: 1 | 2 | undefined}`.
|
|
141
|
+
type RestoreMergedUndefined<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>, Result> =
|
|
142
|
+
IsExactOptionalPropertyTypesEnabled extends true
|
|
143
|
+
? Result
|
|
144
|
+
: {
|
|
145
|
+
[Key in keyof Result]: Key extends MergedTargets<BaseType, RenameMap>
|
|
146
|
+
? Result[Key] | undefined
|
|
147
|
+
: Result[Key];
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
type MergedTargets<BaseType extends object, RenameMap extends Record<PropertyKey, PropertyKey>> =
|
|
151
|
+
// Targets renamed from both a required and an optional key prefer the required modifier.
|
|
152
|
+
// Required `b` and optional `a` both rename to `x` in `{a?: 1; b: 2}` with `{a: 'x'; b: 'x'}`.
|
|
153
|
+
TargetOf<RequiredKeysOf<OmitIndexSignature<BaseType>>, RenameMap>
|
|
154
|
+
& TargetOf<OptionalKeysOf<OmitIndexSignature<BaseType>>, RenameMap>;
|
|
155
|
+
|
|
156
|
+
type NormalizeMap<RenameMap extends Record<PropertyKey, PropertyKey>> = {
|
|
157
|
+
-readonly [Key in keyof RenameMap as true extends IsLiteral<RenameMap[Key]> ? Key : never]-?: RenameMap[Key];
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
type TargetOf<SourceKey extends PropertyKey, RenameMap extends Record<PropertyKey, PropertyKey>> =
|
|
161
|
+
SourceKey extends keyof RenameMap ? RenameMap[SourceKey] : SourceKey;
|
|
162
|
+
|
|
163
|
+
export {};
|
package/source/replace.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ declare function replace<
|
|
|
27
27
|
>(
|
|
28
28
|
input: Input,
|
|
29
29
|
search: Search,
|
|
30
|
-
replacement: Replacement
|
|
30
|
+
replacement: Replacement,
|
|
31
31
|
): Replace<Input, Search, Replacement>;
|
|
32
32
|
|
|
33
33
|
declare function replaceAll<
|
|
@@ -37,7 +37,7 @@ declare function replaceAll<
|
|
|
37
37
|
>(
|
|
38
38
|
input: Input,
|
|
39
39
|
search: Search,
|
|
40
|
-
replacement: Replacement
|
|
40
|
+
replacement: Replacement,
|
|
41
41
|
): Replace<Input, Search, Replacement, {all: true}>;
|
|
42
42
|
|
|
43
43
|
// The return type is the exact string literal, not just `string`.
|
|
@@ -9,7 +9,7 @@ Requires all of the keys in the given object.
|
|
|
9
9
|
type RequireAll<ObjectType, KeysType extends keyof ObjectType> = Required<Pick<ObjectType, KeysType>>;
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
Create a type that requires all of the given keys or none of the given keys
|
|
12
|
+
Create a type that requires all of the given keys or none of the given keys, while keeping the remaining keys as is.
|
|
13
13
|
|
|
14
14
|
Use-cases:
|
|
15
15
|
- Creating interfaces for components with mutually-inclusive keys.
|
|
@@ -40,11 +40,11 @@ const responder2: RequireAllOrNone<Responder, 'text' | 'json'> = {
|
|
|
40
40
|
@category Object
|
|
41
41
|
*/
|
|
42
42
|
export type RequireAllOrNone<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
|
|
43
|
-
IfNotAnyOrNever<ObjectType,
|
|
44
|
-
If<IsNever<KeysType>,
|
|
43
|
+
IfNotAnyOrNever<ObjectType, {
|
|
44
|
+
ifNot: If<IsNever<KeysType>,
|
|
45
45
|
ObjectType,
|
|
46
|
-
_RequireAllOrNone<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType
|
|
47
|
-
|
|
46
|
+
_RequireAllOrNone<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>;
|
|
47
|
+
}>;
|
|
48
48
|
|
|
49
49
|
type _RequireAllOrNone<ObjectType, KeysType extends keyof ObjectType> = (
|
|
50
50
|
| RequireAll<ObjectType, KeysType>
|
|
@@ -5,7 +5,7 @@ import type {IsAny} from './is-any.d.ts';
|
|
|
5
5
|
import type {IsNever} from './is-never.d.ts';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
Create a type that requires at least one of the given keys
|
|
8
|
+
Create a type that requires at least one of the given keys, while keeping the remaining keys as is.
|
|
9
9
|
|
|
10
10
|
@example
|
|
11
11
|
```
|
|
@@ -29,22 +29,20 @@ export type RequireAtLeastOne<
|
|
|
29
29
|
ObjectType,
|
|
30
30
|
KeysType extends keyof ObjectType = keyof ObjectType,
|
|
31
31
|
> =
|
|
32
|
-
IfNotAnyOrNever<ObjectType,
|
|
33
|
-
If<IsNever<KeysType>,
|
|
32
|
+
IfNotAnyOrNever<ObjectType, {
|
|
33
|
+
ifNot: If<IsNever<KeysType>,
|
|
34
34
|
never,
|
|
35
|
-
_RequireAtLeastOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType
|
|
36
|
-
|
|
35
|
+
_RequireAtLeastOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>;
|
|
36
|
+
}>;
|
|
37
37
|
|
|
38
38
|
type _RequireAtLeastOne<
|
|
39
39
|
ObjectType,
|
|
40
40
|
KeysType extends keyof ObjectType,
|
|
41
41
|
> = {
|
|
42
42
|
// For each `Key` in `KeysType` make a mapped type:
|
|
43
|
-
[Key in KeysType]-?: Required<Pick<ObjectType, Key>>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// 3. Add the remaining keys not in `KeysType`
|
|
48
|
-
Except<ObjectType, KeysType>;
|
|
43
|
+
[Key in KeysType]-?: Required<Pick<ObjectType, Key>> // 1. Make `Key`'s type required
|
|
44
|
+
& Partial<Pick<ObjectType, Exclude<KeysType, Key>>>; // 2. Make all other keys in `KeysType` optional
|
|
45
|
+
}[KeysType]
|
|
46
|
+
& Except<ObjectType, KeysType>; // 3. Add the remaining keys not in `KeysType`
|
|
49
47
|
|
|
50
48
|
export {};
|
|
@@ -4,7 +4,7 @@ import type {IsAny} from './is-any.d.ts';
|
|
|
4
4
|
import type {IsNever} from './is-never.d.ts';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
Create a type that requires exactly one of the given keys and disallows more
|
|
7
|
+
Create a type that requires exactly one of the given keys and disallows more, while keeping the remaining keys as is.
|
|
8
8
|
|
|
9
9
|
Use-cases:
|
|
10
10
|
- Creating interfaces for components that only need one of the keys to display properly.
|
|
@@ -33,16 +33,16 @@ const responder: RequireExactlyOne<Responder, 'text' | 'json'> = {
|
|
|
33
33
|
@category Object
|
|
34
34
|
*/
|
|
35
35
|
export type RequireExactlyOne<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
|
|
36
|
-
IfNotAnyOrNever<ObjectType,
|
|
37
|
-
If<IsNever<KeysType>,
|
|
36
|
+
IfNotAnyOrNever<ObjectType, {
|
|
37
|
+
ifNot: If<IsNever<KeysType>,
|
|
38
38
|
never,
|
|
39
|
-
_RequireExactlyOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType
|
|
40
|
-
|
|
39
|
+
_RequireExactlyOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>;
|
|
40
|
+
}>;
|
|
41
41
|
|
|
42
42
|
type _RequireExactlyOne<ObjectType, KeysType extends keyof ObjectType> =
|
|
43
43
|
{[Key in KeysType]: (
|
|
44
|
-
Required<Pick<ObjectType, Key>>
|
|
45
|
-
Partial<Record<Exclude<KeysType, Key>, never>>
|
|
44
|
+
Required<Pick<ObjectType, Key>>
|
|
45
|
+
& Partial<Record<Exclude<KeysType, Key>, never>>
|
|
46
46
|
)}[KeysType] & Omit<ObjectType, KeysType>;
|
|
47
47
|
|
|
48
48
|
export {};
|