type-fest 2.8.0 → 2.11.1
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/index.d.ts +5 -0
- package/package.json +1 -1
- package/readme.md +36 -25
- package/source/delimiter-cased-properties-deep.d.ts +1 -1
- package/source/get.d.ts +55 -13
- package/source/internal.d.ts +7 -0
- package/source/invariant-of.d.ts +72 -0
- package/source/jsonify.d.ts +1 -1
- package/source/literal-to-primitive.d.ts +36 -0
- package/source/literal-union.d.ts +2 -2
- package/source/partial-deep.d.ts +3 -3
- package/source/pascal-cased-properties-deep.d.ts +1 -1
- package/source/readonly-deep.d.ts +27 -6
- package/source/remove-index-signature.d.ts +98 -0
- package/source/schema.d.ts +72 -0
- package/source/string-key-of.d.ts +25 -0
package/index.d.ts
CHANGED
|
@@ -12,11 +12,13 @@ export {MergeExclusive} from './source/merge-exclusive';
|
|
|
12
12
|
export {RequireAtLeastOne} from './source/require-at-least-one';
|
|
13
13
|
export {RequireExactlyOne} from './source/require-exactly-one';
|
|
14
14
|
export {RequireAllOrNone} from './source/require-all-or-none';
|
|
15
|
+
export {RemoveIndexSignature} from './source/remove-index-signature';
|
|
15
16
|
export {PartialDeep} from './source/partial-deep';
|
|
16
17
|
export {ReadonlyDeep} from './source/readonly-deep';
|
|
17
18
|
export {LiteralUnion} from './source/literal-union';
|
|
18
19
|
export {Promisable} from './source/promisable';
|
|
19
20
|
export {Opaque} from './source/opaque';
|
|
21
|
+
export {InvariantOf} from './source/invariant-of';
|
|
20
22
|
export {SetOptional} from './source/set-optional';
|
|
21
23
|
export {SetRequired} from './source/set-required';
|
|
22
24
|
export {ValueOf} from './source/value-of';
|
|
@@ -37,6 +39,8 @@ export {SetReturnType} from './source/set-return-type';
|
|
|
37
39
|
export {Asyncify} from './source/asyncify';
|
|
38
40
|
export {Simplify} from './source/simplify';
|
|
39
41
|
export {Jsonify} from './source/jsonify';
|
|
42
|
+
export {Schema} from './source/schema';
|
|
43
|
+
export {LiteralToPrimitive} from './source/literal-to-primitive';
|
|
40
44
|
export {
|
|
41
45
|
PositiveInfinity,
|
|
42
46
|
NegativeInfinity,
|
|
@@ -49,6 +53,7 @@ export {
|
|
|
49
53
|
NegativeInteger,
|
|
50
54
|
NonNegativeInteger,
|
|
51
55
|
} from './source/numeric';
|
|
56
|
+
export {StringKeyOf} from './source/string-key-of';
|
|
52
57
|
|
|
53
58
|
// Template literal types
|
|
54
59
|
export {CamelCase} from './source/camel-case';
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -88,10 +88,6 @@ Click the type names for complete docs.
|
|
|
88
88
|
- [`Class`](source/basic.d.ts) - Matches a [`class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes).
|
|
89
89
|
- [`Constructor`](source/basic.d.ts) - Matches a [`class` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes).
|
|
90
90
|
- [`TypedArray`](source/typed-array.d.ts) - Matches any [typed array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray), like `Uint8Array` or `Float64Array`.
|
|
91
|
-
- [`JsonPrimitive`](source/basic.d.ts) - Matches a JSON primitive.
|
|
92
|
-
- [`JsonObject`](source/basic.d.ts) - Matches a JSON object.
|
|
93
|
-
- [`JsonArray`](source/basic.d.ts) - Matches a JSON array.
|
|
94
|
-
- [`JsonValue`](source/basic.d.ts) - Matches any valid JSON value.
|
|
95
91
|
- [`ObservableLike`](source/observable-like.d.ts) - Matches a value that is like an [Observable](https://github.com/tc39/proposal-observable).
|
|
96
92
|
|
|
97
93
|
### Utilities
|
|
@@ -103,10 +99,12 @@ Click the type names for complete docs.
|
|
|
103
99
|
- [`RequireAtLeastOne`](source/require-at-least-one.d.ts) - Create a type that requires at least one of the given keys.
|
|
104
100
|
- [`RequireExactlyOne`](source/require-exactly-one.d.ts) - Create a type that requires exactly a single key of the given keys and disallows more.
|
|
105
101
|
- [`RequireAllOrNone`](source/require-all-or-none.d.ts) - Create a type that requires all of the given keys or none of the given keys.
|
|
102
|
+
- [`RemoveIndexSignature`](source/remove-index-signature.d.ts) - Create a type that only has explicitly defined properties, absent of any index signatures.
|
|
106
103
|
- [`PartialDeep`](source/partial-deep.d.ts) - Create a deeply optional version of another type. Use [`Partial<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype) if you only need one level deep.
|
|
107
104
|
- [`ReadonlyDeep`](source/readonly-deep.d.ts) - Create a deeply immutable version of an `object`/`Map`/`Set`/`Array` type. Use [`Readonly<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype) if you only need one level deep.
|
|
108
105
|
- [`LiteralUnion`](source/literal-union.d.ts) - Create a union type by combining primitive types and literal types without sacrificing auto-completion in IDEs for the literal type part of the union. Workaround for [Microsoft/TypeScript#29729](https://github.com/Microsoft/TypeScript/issues/29729).
|
|
109
106
|
- [`Opaque`](source/opaque.d.ts) - Create an [opaque type](https://codemix.com/opaque-types-in-javascript/).
|
|
107
|
+
- [`InvariantOf`](source/invariant-of.d.ts) - Create an [invariant type](https://basarat.gitbook.io/typescript/type-system/type-compatibility#footnote-invariance), which is a type that does not accept supertypes and subtypes.
|
|
110
108
|
- [`SetOptional`](source/set-optional.d.ts) - Create a type that makes the given keys optional.
|
|
111
109
|
- [`SetRequired`](source/set-required.d.ts) - Create a type that makes the given keys required.
|
|
112
110
|
- [`ValueOf`](source/value-of.d.ts) - Create a union of the given object's values, and optionally specify which keys to get the values from.
|
|
@@ -114,14 +112,24 @@ Click the type names for complete docs.
|
|
|
114
112
|
- [`ConditionalPick`](source/conditional-pick.d.ts) - Like `Pick` except it selects properties from a shape where the values extend the given `Condition` type.
|
|
115
113
|
- [`ConditionalExcept`](source/conditional-except.d.ts) - Like `Omit` except it removes properties from a shape where the values extend the given `Condition` type.
|
|
116
114
|
- [`UnionToIntersection`](source/union-to-intersection.d.ts) - Convert a union type to an intersection type.
|
|
115
|
+
- [`LiteralToPrimitive`](source/literal-to-primitive.d.ts) - Convert a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) to the [primitive type](source/primitive.d.ts) it belongs to.
|
|
117
116
|
- [`Stringified`](source/stringified.d.ts) - Create a type with the keys of the given type changed to `string` type.
|
|
118
117
|
- [`IterableElement`](source/iterable-element.d.ts) - Get the element type of an `Iterable`/`AsyncIterable`. For example, an array or a generator.
|
|
119
118
|
- [`Entry`](source/entry.d.ts) - Create a type that represents the type of an entry of a collection.
|
|
120
119
|
- [`Entries`](source/entries.d.ts) - Create a type that represents the type of the entries of a collection.
|
|
121
120
|
- [`SetReturnType`](source/set-return-type.d.ts) - Create a function type with a return type of your choice and the same parameters as the given function type.
|
|
122
121
|
- [`Simplify`](source/simplify.d.ts) - Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
|
|
123
|
-
- [`Jsonify`](source/jsonify.d.ts) - Transform a type to one that is assignable to the `JsonValue` type.
|
|
124
122
|
- [`Get`](source/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.
|
|
123
|
+
- [`StringKeyOf`](source/string-key-of.d.ts) - Get keys of the given type as strings.
|
|
124
|
+
- [`Schema`](source/schema.d.ts) - Create a deep version of another object type where property values are recursively replaced into a given value type.
|
|
125
|
+
|
|
126
|
+
### JSON
|
|
127
|
+
|
|
128
|
+
- [`Jsonify`](source/jsonify.d.ts) - Transform a type to one that is assignable to the `JsonValue` type.
|
|
129
|
+
- [`JsonPrimitive`](source/basic.d.ts) - Matches a JSON primitive.
|
|
130
|
+
- [`JsonObject`](source/basic.d.ts) - Matches a JSON object.
|
|
131
|
+
- [`JsonArray`](source/basic.d.ts) - Matches a JSON array.
|
|
132
|
+
- [`JsonValue`](source/basic.d.ts) - Matches any valid JSON value.
|
|
125
133
|
|
|
126
134
|
### Async
|
|
127
135
|
|
|
@@ -158,22 +166,22 @@ Click the type names for complete docs.
|
|
|
158
166
|
|
|
159
167
|
### Change case
|
|
160
168
|
|
|
161
|
-
- [`CamelCase`](source/camel-case.d.ts)
|
|
162
|
-
- [`CamelCasedProperties`](source/camel-cased-properties.d.ts)
|
|
163
|
-
- [`CamelCasedPropertiesDeep`](source/camel-cased-properties-deep.d.ts)
|
|
164
|
-
- [`KebabCase`](source/kebab-case.d.ts)
|
|
165
|
-
- [`KebabCasedProperties`](source/kebab-cased-properties.d.ts)
|
|
166
|
-
- [`KebabCasedPropertiesDeep`](source/kebab-cased-properties-deep.d.ts)
|
|
167
|
-
- [`PascalCase`](source/pascal-case.d.ts)
|
|
168
|
-
- [`PascalCasedProperties`](source/pascal-cased-properties.d.ts)
|
|
169
|
-
- [`PascalCasedPropertiesDeep`](source/pascal-cased-properties-deep.d.ts)
|
|
170
|
-
- [`SnakeCase`](source/snake-case.d.ts)
|
|
171
|
-
- [`SnakeCasedProperties`](source/snake-cased-properties-deep.d.ts)
|
|
172
|
-
- [`SnakeCasedPropertiesDeep`](source/snake-cased-properties-deep.d.ts)
|
|
169
|
+
- [`CamelCase`](source/camel-case.d.ts) - Convert a string literal to camel-case (`fooBar`).
|
|
170
|
+
- [`CamelCasedProperties`](source/camel-cased-properties.d.ts) - Convert object properties to camel-case (`fooBar`).
|
|
171
|
+
- [`CamelCasedPropertiesDeep`](source/camel-cased-properties-deep.d.ts) - Convert object properties to camel-case recursively (`fooBar`).
|
|
172
|
+
- [`KebabCase`](source/kebab-case.d.ts) - Convert a string literal to kebab-case (`foo-bar`).
|
|
173
|
+
- [`KebabCasedProperties`](source/kebab-cased-properties.d.ts) - Convert a object properties to kebab-case recursively (`foo-bar`).
|
|
174
|
+
- [`KebabCasedPropertiesDeep`](source/kebab-cased-properties-deep.d.ts) - Convert object properties to kebab-case (`foo-bar`).
|
|
175
|
+
- [`PascalCase`](source/pascal-case.d.ts) - Converts a string literal to pascal-case (`FooBar`)
|
|
176
|
+
- [`PascalCasedProperties`](source/pascal-cased-properties.d.ts) - Converts object properties to pascal-case (`FooBar`)
|
|
177
|
+
- [`PascalCasedPropertiesDeep`](source/pascal-cased-properties-deep.d.ts) - Converts object properties to pascal-case (`FooBar`)
|
|
178
|
+
- [`SnakeCase`](source/snake-case.d.ts) - Convert a string literal to snake-case (`foo_bar`).
|
|
179
|
+
- [`SnakeCasedProperties`](source/snake-cased-properties-deep.d.ts) - Convert object properties to snake-case (`foo_bar`).
|
|
180
|
+
- [`SnakeCasedPropertiesDeep`](source/snake-cased-properties-deep.d.ts) - Convert object properties to snake-case recursively (`foo_bar`).
|
|
173
181
|
- [`ScreamingSnakeCase`](source/screaming-snake-case.d.ts) - Convert a string literal to screaming-snake-case (`FOO_BAR`).
|
|
174
|
-
- [`DelimiterCase`](source/delimiter-case.d.ts)
|
|
175
|
-
- [`DelimiterCasedProperties`](source/delimiter-cased-properties.d.ts)
|
|
176
|
-
- [`DelimiterCasedPropertiesDeep`](source/delimiter-cased-properties-deep.d.ts)
|
|
182
|
+
- [`DelimiterCase`](source/delimiter-case.d.ts) - Convert a string literal to a custom string delimiter casing.
|
|
183
|
+
- [`DelimiterCasedProperties`](source/delimiter-cased-properties.d.ts) - Convert object properties to a custom string delimiter casing.
|
|
184
|
+
- [`DelimiterCasedPropertiesDeep`](source/delimiter-cased-properties-deep.d.ts) - Convert object properties to a custom string delimiter casing recursively.
|
|
177
185
|
|
|
178
186
|
### Miscellaneous
|
|
179
187
|
|
|
@@ -184,17 +192,20 @@ Click the type names for complete docs.
|
|
|
184
192
|
|
|
185
193
|
*If we decline a type addition, we will make sure to document the better solution here.*
|
|
186
194
|
|
|
187
|
-
- [`Diff` and `Spread`](https://github.com/sindresorhus/type-fest/pull/7) - The
|
|
195
|
+
- [`Diff` and `Spread`](https://github.com/sindresorhus/type-fest/pull/7) - The pull request author didn't provide any real-world use-cases and the PR went stale. If you think this type is useful, provide some real-world use-cases and we might reconsider.
|
|
188
196
|
- [`Dictionary`](https://github.com/sindresorhus/type-fest/issues/33) - You only save a few characters (`Dictionary<number>` vs `Record<string, number>`) from [`Record`](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type), which is more flexible and well-known. Also, you shouldn't use an object as a dictionary. We have `Map` in JavaScript now.
|
|
189
197
|
- [`ExtractProperties` and `ExtractMethods`](https://github.com/sindresorhus/type-fest/pull/4) - The types violate the single responsibility principle. Instead, refine your types into more granular type hierarchies.
|
|
190
198
|
- [`Url2Json`](https://github.com/sindresorhus/type-fest/pull/262) - Inferring search parameters from a URL string is a cute idea, but not very useful in practice, since search parameters are usually dynamic and defined separately.
|
|
191
|
-
- [`Nullish`](https://github.com/sindresorhus/type-fest/pull/318) - The type only saves a couple of characters, not everyone knows what
|
|
199
|
+
- [`Nullish`](https://github.com/sindresorhus/type-fest/pull/318) - The type only saves a couple of characters, not everyone knows what "nullish" means, and I'm also trying to [get away from `null`](https://github.com/sindresorhus/meta/discussions/7).
|
|
200
|
+
- [`TitleCase`](https://github.com/sindresorhus/type-fest/pull/303) - It's not solving a common need and is a better fit for a separate package.
|
|
201
|
+
- [`ExtendOr` and `ExtendAnd`](https://github.com/sindresorhus/type-fest/pull/247) - The benefits don't outweigh having to learn what they mean.
|
|
192
202
|
|
|
193
203
|
## Alternative type names
|
|
194
204
|
|
|
195
205
|
*If you know one of our types by a different name, add it here for discovery.*
|
|
196
206
|
|
|
197
207
|
- `PartialBy` - See [`SetOptional`](https://github.com/sindresorhus/type-fest/blob/main/source/set-optional.d.ts)
|
|
208
|
+
- `RecordDeep`- See [`Schema`](https://github.com/sindresorhus/type-fest/blob/main/source/schema.d.ts)
|
|
198
209
|
|
|
199
210
|
## Tips
|
|
200
211
|
|
|
@@ -603,7 +614,7 @@ There are many advanced types most users don't know about.
|
|
|
603
614
|
```
|
|
604
615
|
</details>
|
|
605
616
|
|
|
606
|
-
- [`ReturnType<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype)
|
|
617
|
+
- [`ReturnType<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype) - Obtain the return type of a function type.
|
|
607
618
|
<details>
|
|
608
619
|
<summary>
|
|
609
620
|
Example
|
|
@@ -638,7 +649,7 @@ There are many advanced types most users don't know about.
|
|
|
638
649
|
```
|
|
639
650
|
</details>
|
|
640
651
|
|
|
641
|
-
- [`InstanceType<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#instancetypetype)
|
|
652
|
+
- [`InstanceType<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#instancetypetype) - Obtain the instance type of a constructor function type.
|
|
642
653
|
<details>
|
|
643
654
|
<summary>
|
|
644
655
|
Example
|
|
@@ -691,7 +702,7 @@ There are many advanced types most users don't know about.
|
|
|
691
702
|
```
|
|
692
703
|
</details>
|
|
693
704
|
|
|
694
|
-
- [`Omit<T, K>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys)
|
|
705
|
+
- [`Omit<T, K>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys) - Constructs a type by picking all properties from T and then removing K.
|
|
695
706
|
<details>
|
|
696
707
|
<summary>
|
|
697
708
|
Example
|
|
@@ -45,7 +45,7 @@ const result: DelimiterCasedPropertiesDeep<UserWithFriends, '-'> = {
|
|
|
45
45
|
export type DelimiterCasedPropertiesDeep<
|
|
46
46
|
Value,
|
|
47
47
|
Delimiter extends string,
|
|
48
|
-
> = Value extends Function
|
|
48
|
+
> = Value extends Function | Date | RegExp
|
|
49
49
|
? Value
|
|
50
50
|
: Value extends Array<infer U>
|
|
51
51
|
? Array<DelimiterCasedPropertiesDeep<U, Delimiter>>
|
package/source/get.d.ts
CHANGED
|
@@ -1,16 +1,44 @@
|
|
|
1
1
|
import {StringDigit} from '../source/utilities';
|
|
2
2
|
import {Split} from './split';
|
|
3
|
+
import {StringKeyOf} from './string-key-of';
|
|
4
|
+
|
|
5
|
+
type GetOptions = {
|
|
6
|
+
strict?: boolean;
|
|
7
|
+
};
|
|
3
8
|
|
|
4
9
|
/**
|
|
5
10
|
Like the `Get` type but receives an array of strings as a path parameter.
|
|
6
11
|
*/
|
|
7
|
-
type GetWithPath<BaseType, Keys extends readonly string[]> =
|
|
12
|
+
type GetWithPath<BaseType, Keys extends readonly string[], Options extends GetOptions = {}> =
|
|
8
13
|
Keys extends []
|
|
9
14
|
? BaseType
|
|
10
|
-
: Keys extends [infer Head, ...infer Tail]
|
|
11
|
-
? GetWithPath<
|
|
15
|
+
: Keys extends readonly [infer Head, ...infer Tail]
|
|
16
|
+
? GetWithPath<
|
|
17
|
+
PropertyOf<BaseType, Extract<Head, string>, Options>,
|
|
18
|
+
Extract<Tail, string[]>,
|
|
19
|
+
Options
|
|
20
|
+
>
|
|
12
21
|
: never;
|
|
13
22
|
|
|
23
|
+
/**
|
|
24
|
+
Adds `undefined` to `Type` if `strict` is enabled.
|
|
25
|
+
*/
|
|
26
|
+
type Strictify<Type, Options extends GetOptions> =
|
|
27
|
+
Options['strict'] extends true ? Type | undefined : Type;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
If `Options['strict']` is `true`, includes `undefined` in the returned type when accessing properties on `Record<string, any>`.
|
|
31
|
+
|
|
32
|
+
Known limitations:
|
|
33
|
+
- Does not include `undefined` in the type on object types with an index signature (for example, `{a: string; [key: string]: string}`).
|
|
34
|
+
*/
|
|
35
|
+
type StrictPropertyOf<BaseType, Key extends keyof BaseType, Options extends GetOptions> =
|
|
36
|
+
Record<string, any> extends BaseType
|
|
37
|
+
? string extends keyof BaseType
|
|
38
|
+
? Strictify<BaseType[Key], Options> // Record<string, any>
|
|
39
|
+
: BaseType[Key] // Record<'a' | 'b', any> (Records with a string union as keys have required properties)
|
|
40
|
+
: BaseType[Key];
|
|
41
|
+
|
|
14
42
|
/**
|
|
15
43
|
Splits a dot-prop style path into a tuple comprised of the properties in the path. Handles square-bracket notation.
|
|
16
44
|
|
|
@@ -29,8 +57,12 @@ type ToPath<S extends string> = Split<FixPathSquareBrackets<S>, '.'>;
|
|
|
29
57
|
Replaces square-bracketed dot notation with dots, for example, `foo[0].bar` -> `foo.0.bar`.
|
|
30
58
|
*/
|
|
31
59
|
type FixPathSquareBrackets<Path extends string> =
|
|
32
|
-
Path extends
|
|
33
|
-
?
|
|
60
|
+
Path extends `[${infer Head}]${infer Tail}`
|
|
61
|
+
? Tail extends `[${string}`
|
|
62
|
+
? `${Head}.${FixPathSquareBrackets<Tail>}`
|
|
63
|
+
: `${Head}${FixPathSquareBrackets<Tail>}`
|
|
64
|
+
: Path extends `${infer Head}[${infer Middle}]${infer Tail}`
|
|
65
|
+
? `${Head}.${FixPathSquareBrackets<`[${Middle}]${Tail}`>}`
|
|
34
66
|
: Path;
|
|
35
67
|
|
|
36
68
|
/**
|
|
@@ -66,7 +98,7 @@ type WithStringsKeys = keyof WithStrings;
|
|
|
66
98
|
```
|
|
67
99
|
*/
|
|
68
100
|
type WithStringKeys<BaseType extends Record<string | number, any>> = {
|
|
69
|
-
[Key in
|
|
101
|
+
[Key in StringKeyOf<BaseType>]: BaseType[Key]
|
|
70
102
|
};
|
|
71
103
|
|
|
72
104
|
/**
|
|
@@ -76,11 +108,11 @@ Note:
|
|
|
76
108
|
- Returns `unknown` if `Key` is not a property of `BaseType`, since TypeScript uses structural typing, and it cannot be guaranteed that extra properties unknown to the type system will exist at runtime.
|
|
77
109
|
- Returns `undefined` from nullish values, to match the behaviour of most deep-key libraries like `lodash`, `dot-prop`, etc.
|
|
78
110
|
*/
|
|
79
|
-
type PropertyOf<BaseType, Key extends string> =
|
|
111
|
+
type PropertyOf<BaseType, Key extends string, Options extends GetOptions = {}> =
|
|
80
112
|
BaseType extends null | undefined
|
|
81
113
|
? undefined
|
|
82
114
|
: Key extends keyof BaseType
|
|
83
|
-
? BaseType
|
|
115
|
+
? StrictPropertyOf<BaseType, Key, Options>
|
|
84
116
|
: BaseType extends [] | [unknown, ...unknown[]]
|
|
85
117
|
? unknown // It's a tuple, but `Key` did not extend `keyof BaseType`. So the index is out of bounds.
|
|
86
118
|
: BaseType extends {
|
|
@@ -89,11 +121,11 @@ type PropertyOf<BaseType, Key extends string> =
|
|
|
89
121
|
}
|
|
90
122
|
? (
|
|
91
123
|
ConsistsOnlyOf<Key, StringDigit> extends true
|
|
92
|
-
? Item
|
|
124
|
+
? Strictify<Item, Options>
|
|
93
125
|
: unknown
|
|
94
126
|
)
|
|
95
127
|
: Key extends keyof WithStringKeys<BaseType>
|
|
96
|
-
? WithStringKeys<BaseType>
|
|
128
|
+
? StrictPropertyOf<WithStringKeys<BaseType>, Key, Options>
|
|
97
129
|
: unknown;
|
|
98
130
|
|
|
99
131
|
// This works by first splitting the path based on `.` and `[...]` characters into a tuple of string keys. Then it recursively uses the head key to get the next property of the current object, until there are no keys left. Number keys extract the item type from arrays, or are converted to strings to extract types from tuples and dictionaries with number keys.
|
|
@@ -107,7 +139,7 @@ Use-case: Retrieve a property from deep inside an API response or some other com
|
|
|
107
139
|
import {Get} from 'type-fest';
|
|
108
140
|
import * as lodash from 'lodash';
|
|
109
141
|
|
|
110
|
-
const get = <BaseType, Path extends string>(object: BaseType, path: Path): Get<BaseType, Path> =>
|
|
142
|
+
const get = <BaseType, Path extends string | readonly string[]>(object: BaseType, path: Path): Get<BaseType, Path> =>
|
|
111
143
|
lodash.get(object, path);
|
|
112
144
|
|
|
113
145
|
interface ApiResponse {
|
|
@@ -128,10 +160,20 @@ interface ApiResponse {
|
|
|
128
160
|
const getName = (apiResponse: ApiResponse) =>
|
|
129
161
|
get(apiResponse, 'hits.hits[0]._source.name');
|
|
130
162
|
//=> Array<{given: string[]; family: string}>
|
|
163
|
+
|
|
164
|
+
// Path also supports a readonly array of strings
|
|
165
|
+
const getNameWithPathArray = (apiResponse: ApiResponse) =>
|
|
166
|
+
get(apiResponse, ['hits','hits', '0', '_source', 'name'] as const);
|
|
167
|
+
//=> Array<{given: string[]; family: string}>
|
|
168
|
+
|
|
169
|
+
// Strict mode:
|
|
170
|
+
Get<string[], '3', {strict: true}> //=> string | undefined
|
|
171
|
+
Get<Record<string, string>, 'foo', {strict: true}> // => string | undefined
|
|
131
172
|
```
|
|
132
173
|
|
|
133
|
-
@category Template literal
|
|
134
174
|
@category Object
|
|
135
175
|
@category Array
|
|
176
|
+
@category Template literal
|
|
136
177
|
*/
|
|
137
|
-
export type Get<BaseType, Path extends string
|
|
178
|
+
export type Get<BaseType, Path extends string | readonly string[], Options extends GetOptions = {}> =
|
|
179
|
+
GetWithPath<BaseType, Path extends string ? ToPath<Path> : Path, Options>;
|
package/source/internal.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import {Primitive} from './primitive';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
Returns a boolean for whether the two given types are equal.
|
|
3
5
|
|
|
@@ -35,3 +37,8 @@ the inferred tuple `U` and a tuple of length `B`, then extracts the length of tu
|
|
|
35
37
|
export type Subtract<A extends number, B extends number> = BuildTuple<A> extends [...(infer U), ...BuildTuple<B>]
|
|
36
38
|
? TupleLength<U>
|
|
37
39
|
: never;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
Matches any primitive, `Date`, or `RegExp` value.
|
|
43
|
+
*/
|
|
44
|
+
export type BuiltIns = Primitive | Date | RegExp;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {Opaque} from './opaque';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Create an [invariant type](https://basarat.gitbook.io/typescript/type-system/type-compatibility#footnote-invariance), which is a type that does not accept supertypes and subtypes.
|
|
5
|
+
|
|
6
|
+
Use-case:
|
|
7
|
+
- Prevent runtime errors that may occur due to assigning subtypes to supertypes.
|
|
8
|
+
- Improve type signature of object methods like [`Object.keys()` or `Object.entries()`](https://github.com/microsoft/TypeScript/pull/12253#issuecomment-263132208) by sealing the object type.
|
|
9
|
+
|
|
10
|
+
@example
|
|
11
|
+
```
|
|
12
|
+
class Animal {
|
|
13
|
+
constructor(public name: string){}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class Cat extends Animal {
|
|
17
|
+
meow() {}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let animalArray: Animal[] = [animal];
|
|
21
|
+
let catArray: Cat[] = [cat];
|
|
22
|
+
|
|
23
|
+
animalArray = catArray; // Okay if covariant
|
|
24
|
+
animalArray.push(new Animal('another animal')); // Pushed an animal into catArray
|
|
25
|
+
catArray.forEach(c => c.meow()); // Allowed but, error at runtime
|
|
26
|
+
|
|
27
|
+
let invariantAnimalArray: InvariantOf<Animal>[] = [animal] as InvariantOf<Animal>[];
|
|
28
|
+
let invariantCatArray: InvariantOf<Cat>[] = [cat] as InvariantOf<Cat>[];
|
|
29
|
+
|
|
30
|
+
invariantAnimalArray = invariantCatArray; // Error: Type 'InvariantOf<Cat>[]' is not assignable to type 'InvariantOf<Animal>[]'.
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
@example
|
|
34
|
+
```
|
|
35
|
+
// In covariance (default)
|
|
36
|
+
|
|
37
|
+
interface FooBar {
|
|
38
|
+
foo: number;
|
|
39
|
+
bar: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface FooBarBaz extends FooBar {
|
|
43
|
+
baz: boolean
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
declare const fooBar: FooBar
|
|
47
|
+
declare const fooBarBaz: FooBarBaz
|
|
48
|
+
|
|
49
|
+
function keyOfFooBar(fooBar: FooBar) {
|
|
50
|
+
return Object.keys(fooBar) as (keyof FooBar)[]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
keyOfFooBar(fooBar) //=> (keyof FooBar)[]
|
|
54
|
+
keyOfFooBar(fooBarBaz) //=> (keyof FooBar)[] but, (keyof FooBarBaz)[] at runtime
|
|
55
|
+
|
|
56
|
+
// In invariance
|
|
57
|
+
|
|
58
|
+
export function invariantOf<Type>(value: Type): InvariantOf<Type> {
|
|
59
|
+
return value as InvariantOf<Type>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function keyOfInvariantFooBar(fooBar: InvariantOf<FooBar>) {
|
|
63
|
+
return Object.keys(fooBar) as (keyof FooBar)[]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
keyOfInvariantFooBar(invariantOf(fooBar)); // (keyof FooBar)[]
|
|
67
|
+
keyOfInvariantFooBar(invariantOf(fooBarBaz)); // Error: Argument of type 'InvariantOf<FooBarBaz>' is not assignable to parameter of type 'InvariantOf<FooBar>'.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
@category Type
|
|
71
|
+
*/
|
|
72
|
+
export type InvariantOf<Type> = Opaque<Type, (argument: Type) => Type>;
|
package/source/jsonify.d.ts
CHANGED
|
@@ -70,6 +70,6 @@ type Jsonify<T> =
|
|
|
70
70
|
? (() => J) extends (() => JsonValue) // Is J assignable to JsonValue?
|
|
71
71
|
? J // Then T is Jsonable and its Jsonable value is J
|
|
72
72
|
: never // Not Jsonable because its toJSON() method does not return JsonValue
|
|
73
|
-
: {[P in keyof T]: Jsonify<T[P]>} // It's an object: recursive call for its children
|
|
73
|
+
: {[P in keyof T]: Jsonify<Required<T>[P]>} // It's an object: recursive call for its children
|
|
74
74
|
: never // Otherwise any other non-object is removed
|
|
75
75
|
: never; // Otherwise non-JSONable type union was found not empty
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Given a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) return the {@link Primitive | primitive type} it belongs to, or `never` if it's not a primitive.
|
|
3
|
+
|
|
4
|
+
Use-case: Working with generic types that may be literal types.
|
|
5
|
+
|
|
6
|
+
@example
|
|
7
|
+
```
|
|
8
|
+
import {LiteralToPrimitive} from 'type-fest';
|
|
9
|
+
|
|
10
|
+
// No overloads needed to get the correct return type
|
|
11
|
+
function plus<T extends number | bigint | string>(x: T, y: T): LiteralToPrimitive<T> {
|
|
12
|
+
return x + (y as any);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
plus('a', 'b'); // string
|
|
16
|
+
plus(1, 2); // number
|
|
17
|
+
plus(1n, 2n); // bigint
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
@category Type
|
|
21
|
+
*/
|
|
22
|
+
export type LiteralToPrimitive<T> = T extends number
|
|
23
|
+
? number
|
|
24
|
+
: T extends bigint
|
|
25
|
+
? bigint
|
|
26
|
+
: T extends string
|
|
27
|
+
? string
|
|
28
|
+
: T extends boolean
|
|
29
|
+
? boolean
|
|
30
|
+
: T extends symbol
|
|
31
|
+
? symbol
|
|
32
|
+
: T extends null
|
|
33
|
+
? null
|
|
34
|
+
: T extends undefined
|
|
35
|
+
? undefined
|
|
36
|
+
: never;
|
package/source/partial-deep.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {BuiltIns} from './internal';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
Create a type from another type with all keys and nested keys set to optional.
|
|
@@ -33,8 +33,8 @@ settings = applySavedSettings({textEditor: {fontWeight: 500}});
|
|
|
33
33
|
@category Set
|
|
34
34
|
@category Map
|
|
35
35
|
*/
|
|
36
|
-
export type PartialDeep<T> = T extends
|
|
37
|
-
?
|
|
36
|
+
export type PartialDeep<T> = T extends BuiltIns
|
|
37
|
+
? T
|
|
38
38
|
: T extends Map<infer KeyType, infer ValueType>
|
|
39
39
|
? PartialMapDeep<KeyType, ValueType>
|
|
40
40
|
: T extends Set<infer ItemType>
|
|
@@ -42,7 +42,7 @@ const result: PascalCasedPropertiesDeep<UserWithFriends> = {
|
|
|
42
42
|
@category Template literal
|
|
43
43
|
@category Object
|
|
44
44
|
*/
|
|
45
|
-
export type PascalCasedPropertiesDeep<Value> = Value extends Function
|
|
45
|
+
export type PascalCasedPropertiesDeep<Value> = Value extends Function | Date | RegExp
|
|
46
46
|
? Value
|
|
47
47
|
: Value extends Array<infer U>
|
|
48
48
|
? Array<PascalCasedPropertiesDeep<U>>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {BuiltIns} from './internal';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
Convert `object`s, `Map`s, `Set`s, and `Array`s and all of their keys/elements into immutable structures recursively.
|
|
@@ -34,11 +34,17 @@ data.foo.push('bar');
|
|
|
34
34
|
@category Set
|
|
35
35
|
@category Map
|
|
36
36
|
*/
|
|
37
|
-
export type ReadonlyDeep<T> = T extends
|
|
37
|
+
export type ReadonlyDeep<T> = T extends BuiltIns
|
|
38
38
|
? T
|
|
39
|
-
: T extends
|
|
39
|
+
: T extends (...arguments: any[]) => unknown
|
|
40
|
+
? {} extends ReadonlyObjectDeep<T>
|
|
41
|
+
? T
|
|
42
|
+
: HasMultipleCallSignatures<T> extends true
|
|
43
|
+
? T
|
|
44
|
+
: ((...arguments: Parameters<T>) => ReturnType<T>) & ReadonlyObjectDeep<T>
|
|
45
|
+
: T extends Readonly<ReadonlyMap<infer KeyType, infer ValueType>>
|
|
40
46
|
? ReadonlyMapDeep<KeyType, ValueType>
|
|
41
|
-
: T extends ReadonlySet<infer ItemType
|
|
47
|
+
: T extends Readonly<ReadonlySet<infer ItemType>>
|
|
42
48
|
? ReadonlySetDeep<ItemType>
|
|
43
49
|
: T extends object
|
|
44
50
|
? ReadonlyObjectDeep<T>
|
|
@@ -48,13 +54,13 @@ export type ReadonlyDeep<T> = T extends Primitive | ((...arguments: any[]) => un
|
|
|
48
54
|
Same as `ReadonlyDeep`, but accepts only `ReadonlyMap`s as inputs. Internal helper for `ReadonlyDeep`.
|
|
49
55
|
*/
|
|
50
56
|
interface ReadonlyMapDeep<KeyType, ValueType>
|
|
51
|
-
extends ReadonlyMap<ReadonlyDeep<KeyType>, ReadonlyDeep<ValueType
|
|
57
|
+
extends Readonly<ReadonlyMap<ReadonlyDeep<KeyType>, ReadonlyDeep<ValueType>>> {}
|
|
52
58
|
|
|
53
59
|
/**
|
|
54
60
|
Same as `ReadonlyDeep`, but accepts only `ReadonlySet`s as inputs. Internal helper for `ReadonlyDeep`.
|
|
55
61
|
*/
|
|
56
62
|
interface ReadonlySetDeep<ItemType>
|
|
57
|
-
extends ReadonlySet<ReadonlyDeep<ItemType
|
|
63
|
+
extends Readonly<ReadonlySet<ReadonlyDeep<ItemType>>> {}
|
|
58
64
|
|
|
59
65
|
/**
|
|
60
66
|
Same as `ReadonlyDeep`, but accepts only `object`s as inputs. Internal helper for `ReadonlyDeep`.
|
|
@@ -62,3 +68,18 @@ Same as `ReadonlyDeep`, but accepts only `object`s as inputs. Internal helper fo
|
|
|
62
68
|
type ReadonlyObjectDeep<ObjectType extends object> = {
|
|
63
69
|
readonly [KeyType in keyof ObjectType]: ReadonlyDeep<ObjectType[KeyType]>
|
|
64
70
|
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
Test if the given function has multiple call signatures.
|
|
74
|
+
|
|
75
|
+
Needed to handle the case of a single call signature with properties.
|
|
76
|
+
|
|
77
|
+
Multiple call signatures cannot currently be supported due to a TypeScript limitation.
|
|
78
|
+
@see https://github.com/microsoft/TypeScript/issues/29732
|
|
79
|
+
*/
|
|
80
|
+
type HasMultipleCallSignatures<T extends (...arguments: any[]) => unknown> =
|
|
81
|
+
T extends {(...arguments: infer A): unknown; (...arguments: any[]): unknown}
|
|
82
|
+
? unknown[] extends A
|
|
83
|
+
? false
|
|
84
|
+
: true
|
|
85
|
+
: false;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Remove any index signatures from the given object type, so that only explicitly defined properties remain.
|
|
3
|
+
|
|
4
|
+
Use-cases:
|
|
5
|
+
- Remove overly permissive signatures from third-party types.
|
|
6
|
+
|
|
7
|
+
This type was taken from this [StackOverflow answer](https://stackoverflow.com/a/68261113/420747).
|
|
8
|
+
|
|
9
|
+
It relies on the fact that an empty object (`{}`) is assignable to an object with just an index signature, like `Record<string, unknown>`, but not to an object with explicitly defined keys, like `Record<'foo' | 'bar', unknown>`.
|
|
10
|
+
|
|
11
|
+
(The actual value type, `unknown`, is irrelevant and could be any type. Only the key type matters.)
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
const indexed: Record<string, unknown> = {}; // Allowed
|
|
15
|
+
|
|
16
|
+
const keyed: Record<'foo', unknown> = {}; // Error
|
|
17
|
+
// => TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Instead of causing a type error like the above, you can also use a [conditional type](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html) to test whether a type is assignable to another:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
type Indexed = {} extends Record<string, unknown>
|
|
24
|
+
? '✅ `{}` is assignable to `Record<string, unknown>`'
|
|
25
|
+
: '❌ `{}` is NOT assignable to `Record<string, unknown>`';
|
|
26
|
+
// => '✅ `{}` is assignable to `Record<string, unknown>`'
|
|
27
|
+
|
|
28
|
+
type Keyed = {} extends Record<'foo' | 'bar', unknown>
|
|
29
|
+
? "✅ `{}` is assignable to `Record<'foo' | 'bar', unknown>`"
|
|
30
|
+
: "❌ `{}` is NOT assignable to `Record<'foo' | 'bar', unknown>`";
|
|
31
|
+
// => "❌ `{}` is NOT assignable to `Record<'foo' | 'bar', unknown>`"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Using a [mapped type](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#further-exploration), you can then check for each `KeyType` of `ObjectType`...
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
type RemoveIndexSignature<ObjectType> = {
|
|
38
|
+
[KeyType in keyof ObjectType // Map each key of `ObjectType`...
|
|
39
|
+
]: ObjectType[KeyType]; // ...to its original value, i.e. `RemoveIndexSignature<Foo> == Foo`.
|
|
40
|
+
};
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
...whether an empty object (`{}`) would be assignable to an object with that `KeyType` (`Record<KeyType, unknown>`)...
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
type RemoveIndexSignature<ObjectType> = {
|
|
47
|
+
[KeyType in keyof ObjectType
|
|
48
|
+
// Is `{}` assignable to `Record<KeyType, unknown>`?
|
|
49
|
+
as {} extends Record<KeyType, unknown>
|
|
50
|
+
? ... // ✅ `{}` is assignable to `Record<KeyType, unknown>`
|
|
51
|
+
: ... // ❌ `{}` is NOT assignable to `Record<KeyType, unknown>`
|
|
52
|
+
]: ObjectType[KeyType];
|
|
53
|
+
};
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If `{}` is assignable, it means that `KeyType` is an index signature and we want to remove it. If it is not assignable, `KeyType` is a "real" key and we want to keep it.
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
type RemoveIndexSignature<ObjectType> = {
|
|
60
|
+
[KeyType in keyof ObjectType
|
|
61
|
+
as {} extends Record<KeyType, unknown>
|
|
62
|
+
? never // => Remove this `KeyType`.
|
|
63
|
+
: KeyType // => Keep this `KeyType` as it is.
|
|
64
|
+
]: ObjectType[KeyType];
|
|
65
|
+
};
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
@example
|
|
69
|
+
```
|
|
70
|
+
import {RemoveIndexSignature} from 'type-fest';
|
|
71
|
+
|
|
72
|
+
interface Example {
|
|
73
|
+
// These index signatures will be removed.
|
|
74
|
+
[x: string]: any
|
|
75
|
+
[x: number]: any
|
|
76
|
+
[x: symbol]: any
|
|
77
|
+
[x: `head-${string}`]: string
|
|
78
|
+
[x: `${string}-tail`]: string
|
|
79
|
+
[x: `head-${string}-tail`]: string
|
|
80
|
+
[x: `${bigint}`]: string
|
|
81
|
+
[x: `embedded-${number}`]: string
|
|
82
|
+
|
|
83
|
+
// These explicitly defined keys will remain.
|
|
84
|
+
foo: 'bar';
|
|
85
|
+
qux?: 'baz';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
type ExampleWithoutIndexSignatures = RemoveIndexSignature<Example>;
|
|
89
|
+
// => { foo: 'bar'; qux?: 'baz' | undefined; }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
@category Object
|
|
93
|
+
*/
|
|
94
|
+
export type RemoveIndexSignature<ObjectType> = {
|
|
95
|
+
[KeyType in keyof ObjectType as {} extends Record<KeyType, unknown>
|
|
96
|
+
? never
|
|
97
|
+
: KeyType]: ObjectType[KeyType];
|
|
98
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Create a deep version of another object type where property values are recursively replaced into a given value type.
|
|
3
|
+
|
|
4
|
+
Use-cases:
|
|
5
|
+
- Form validation: Define how each field should be validated.
|
|
6
|
+
- Form settings: Define configuration for input fields.
|
|
7
|
+
- Parsing: Define types that specify special behavior for specific fields.
|
|
8
|
+
|
|
9
|
+
@example
|
|
10
|
+
```
|
|
11
|
+
import {Schema} from 'type-fest';
|
|
12
|
+
|
|
13
|
+
interface User {
|
|
14
|
+
id: string;
|
|
15
|
+
name: {
|
|
16
|
+
firstname: string;
|
|
17
|
+
lastname: string;
|
|
18
|
+
};
|
|
19
|
+
created: Date;
|
|
20
|
+
active: boolean;
|
|
21
|
+
passwordHash: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type UserMask = Schema<User, 'mask' | 'hide' | 'show'>;
|
|
25
|
+
|
|
26
|
+
const userMaskSettings: UserMask = {
|
|
27
|
+
id: 'show',
|
|
28
|
+
name: {
|
|
29
|
+
firstname: 'show',
|
|
30
|
+
lastname: 'mask',
|
|
31
|
+
},
|
|
32
|
+
phoneNumbers: 'mask',
|
|
33
|
+
created: 'show',
|
|
34
|
+
active: 'show',
|
|
35
|
+
passwordHash: 'hide',
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
@category Object
|
|
40
|
+
*/
|
|
41
|
+
export type Schema<ObjectType, ValueType> = ObjectType extends string
|
|
42
|
+
? ValueType
|
|
43
|
+
: ObjectType extends Map<unknown, unknown>
|
|
44
|
+
? ValueType
|
|
45
|
+
: ObjectType extends Set<unknown>
|
|
46
|
+
? ValueType
|
|
47
|
+
: ObjectType extends ReadonlyMap<unknown, unknown>
|
|
48
|
+
? ValueType
|
|
49
|
+
: ObjectType extends ReadonlySet<unknown>
|
|
50
|
+
? ValueType
|
|
51
|
+
: ObjectType extends readonly unknown[]
|
|
52
|
+
? ValueType
|
|
53
|
+
: ObjectType extends unknown[]
|
|
54
|
+
? ValueType
|
|
55
|
+
: ObjectType extends (...arguments: unknown[]) => unknown
|
|
56
|
+
? ValueType
|
|
57
|
+
: ObjectType extends Date
|
|
58
|
+
? ValueType
|
|
59
|
+
: ObjectType extends Function
|
|
60
|
+
? ValueType
|
|
61
|
+
: ObjectType extends RegExp
|
|
62
|
+
? ValueType
|
|
63
|
+
: ObjectType extends object
|
|
64
|
+
? SchemaObject<ObjectType, ValueType>
|
|
65
|
+
: ValueType;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
Same as `Schema`, but accepts only `object`s as inputs. Internal helper for `Schema`.
|
|
69
|
+
*/
|
|
70
|
+
type SchemaObject<ObjectType extends object, K> = {
|
|
71
|
+
[KeyType in keyof ObjectType]: Schema<ObjectType[KeyType], K> | K;
|
|
72
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Get keys of the given type as strings.
|
|
3
|
+
|
|
4
|
+
Number keys are converted to strings.
|
|
5
|
+
|
|
6
|
+
Use-cases:
|
|
7
|
+
- Get string keys from a type which may have number keys.
|
|
8
|
+
- Makes it possible to index using strings retrieved from template types.
|
|
9
|
+
|
|
10
|
+
@example
|
|
11
|
+
```
|
|
12
|
+
import {StringKeyOf} from 'type-fest';
|
|
13
|
+
|
|
14
|
+
type Foo = {
|
|
15
|
+
1: number,
|
|
16
|
+
stringKey: string,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type StringKeysOfFoo = StringKeyOf<Foo>;
|
|
20
|
+
//=> '1' | 'stringKey'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
@category Object
|
|
24
|
+
*/
|
|
25
|
+
export type StringKeyOf<BaseType> = `${Extract<keyof BaseType, string | number>}`;
|