type-fest 3.1.0 → 3.3.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/index.d.ts CHANGED
@@ -50,6 +50,7 @@ export type {SetReturnType} from './source/set-return-type';
50
50
  export type {Asyncify} from './source/asyncify';
51
51
  export type {Simplify} from './source/simplify';
52
52
  export type {Jsonify} from './source/jsonify';
53
+ export type {Jsonifiable} from './source/jsonifiable';
53
54
  export type {Schema} from './source/schema';
54
55
  export type {LiteralToPrimitive} from './source/literal-to-primitive';
55
56
  export type {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-fest",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "description": "A collection of essential TypeScript types",
5
5
  "license": "(MIT OR CC0-1.0)",
6
6
  "repository": "sindresorhus/type-fest",
@@ -35,10 +35,10 @@
35
35
  ],
36
36
  "devDependencies": {
37
37
  "@sindresorhus/tsconfig": "~0.7.0",
38
- "expect-type": "^0.14.2",
38
+ "expect-type": "^0.15.0",
39
39
  "tsd": "^0.24.1",
40
- "typescript": "^4.8.3",
41
- "xo": "^0.52.2"
40
+ "typescript": "^4.9.3",
41
+ "xo": "^0.53.1"
42
42
  },
43
43
  "xo": {
44
44
  "rules": {
package/readme.md CHANGED
@@ -68,20 +68,6 @@
68
68
  </sub>
69
69
  </div>
70
70
  </a>
71
- <br>
72
- <br>
73
- <a href="https://sizzy.co/?utm_campaign=github_repo&utm_source=github&utm_medium=referral&utm_content=type-fest&utm_term=sindre">
74
- <div>
75
- <img src="https://sindresorhus.com/assets/thanks/sizzy-logo.png" width="240" alt="Sizzy">
76
- </div>
77
- <div>
78
- <sub>
79
- <b>Before Sizzy:</b> web development is stressing you out, responsive design is hard, you have an overwhelming amount of opened tabs & apps.
80
- <br>
81
- <b>After Sizzy:</b> all the tools you need in one place, responsive design is a breeze, no more context switching.
82
- </sub>
83
- </div>
84
- </a>
85
71
  </p>
86
72
  </div>
87
73
  <br>
@@ -187,6 +173,7 @@ Click the type names for complete docs.
187
173
  ### JSON
188
174
 
189
175
  - [`Jsonify`](source/jsonify.d.ts) - Transform a type to one that is assignable to the `JsonValue` type.
176
+ - [`Jsonifiable`](source/jsonifiable.d.ts) - Matches a value that can be losslessly converted to JSON.
190
177
  - [`JsonPrimitive`](source/basic.d.ts) - Matches a JSON primitive.
191
178
  - [`JsonObject`](source/basic.d.ts) - Matches a JSON object.
192
179
  - [`JsonArray`](source/basic.d.ts) - Matches a JSON array.
@@ -213,7 +200,7 @@ Click the type names for complete docs.
213
200
  - [`MultidimensionalArray`](source/multidimensional-array.d.ts) - Create a type that represents a multidimensional array of the given type and dimensions.
214
201
  - [`MultidimensionalReadonlyArray`](source/multidimensional-readonly-array.d.ts) - Create a type that represents a multidimensional readonly array of the given type and dimensions.
215
202
  - [`ReadonlyTuple`](source/readonly-tuple.d.ts) - Create a type that represents a read-only tuple of the given type and length.
216
- - [`TupleToUnion`](source/tuple-to-union.d.ts) - Convert a tuple into a union type of its elements.
203
+ - [`TupleToUnion`](source/tuple-to-union.d.ts) - Convert a tuple/array into a union type of its elements.
217
204
 
218
205
  ### Numeric
219
206
 
@@ -1,39 +1,42 @@
1
- import type {WordSeparators} from '../source/internal';
2
- import type {Split} from './split';
1
+ import type {SplitWords} from './split-words';
3
2
 
4
3
  /**
5
- Step by step takes the first item in an array literal, formats it and adds it to a string literal, and then recursively appends the remainder.
4
+ CamelCase options.
6
5
 
7
- Only to be used by `CamelCaseStringArray<>`.
8
-
9
- @see CamelCaseStringArray
6
+ @see {@link CamelCase}
10
7
  */
11
- type InnerCamelCaseStringArray<Parts extends readonly any[], PreviousPart> =
12
- Parts extends [`${infer FirstPart}`, ...infer RemainingParts]
13
- ? FirstPart extends undefined
14
- ? ''
15
- : FirstPart extends ''
16
- ? InnerCamelCaseStringArray<RemainingParts, PreviousPart>
17
- : `${PreviousPart extends '' ? FirstPart : Capitalize<FirstPart>}${InnerCamelCaseStringArray<RemainingParts, FirstPart>}`
18
- : '';
19
-
20
- /**
21
- Starts fusing the output of `Split<>`, an array literal of strings, into a camel-cased string literal.
8
+ export type CamelCaseOptions = {
9
+ /**
10
+ Whether to preserved consecutive uppercase letter.
22
11
 
23
- It's separate from `InnerCamelCaseStringArray<>` to keep a clean API outwards to the rest of the code.
12
+ @default true
13
+ */
14
+ preserveConsecutiveUppercase?: boolean;
15
+ };
24
16
 
25
- @see Split
17
+ /**
18
+ Convert an array of words to camel-case.
26
19
  */
27
- type CamelCaseStringArray<Parts extends readonly string[]> =
28
- Parts extends [`${infer FirstPart}`, ...infer RemainingParts]
29
- ? Uncapitalize<`${FirstPart}${InnerCamelCaseStringArray<RemainingParts, FirstPart>}`>
30
- : never;
20
+ type CamelCaseFromArray<
21
+ Words extends string[],
22
+ Options extends CamelCaseOptions,
23
+ OutputString extends string = '',
24
+ > = Words extends [
25
+ infer FirstWord extends string,
26
+ ...infer RemainingWords extends string[],
27
+ ]
28
+ ? Options['preserveConsecutiveUppercase'] extends true
29
+ ? `${Capitalize<FirstWord>}${CamelCaseFromArray<RemainingWords, Options>}`
30
+ : `${Capitalize<Lowercase<FirstWord>>}${CamelCaseFromArray<RemainingWords, Options>}`
31
+ : OutputString;
31
32
 
32
33
  /**
33
34
  Convert a string literal to camel-case.
34
35
 
35
36
  This can be useful when, for example, converting some kebab-cased command-line flags or a snake-cased database result.
36
37
 
38
+ By default, consecutive uppercase letter are preserved. See {@link CamelCaseOptions.preserveConsecutiveUppercase preserveConsecutiveUppercase} option to change this behaviour.
39
+
37
40
  @example
38
41
  ```
39
42
  import type {CamelCase} from 'type-fest';
@@ -70,4 +73,6 @@ const dbResult: CamelCasedProperties<RawOptions> = {
70
73
  @category Change case
71
74
  @category Template literal
72
75
  */
73
- export type CamelCase<K> = K extends string ? CamelCaseStringArray<Split<K extends Uppercase<K> ? Lowercase<K> : K, WordSeparators>> : K;
76
+ export type CamelCase<Type, Options extends CamelCaseOptions = {preserveConsecutiveUppercase: true}> = Type extends string
77
+ ? Uncapitalize<CamelCaseFromArray<SplitWords<Type extends Uppercase<Type> ? Lowercase<Type> : Type>, Options>>
78
+ : Type;
@@ -1,4 +1,4 @@
1
- import type {CamelCase} from './camel-case';
1
+ import type {CamelCase, CamelCaseOptions} from './camel-case';
2
2
 
3
3
  /**
4
4
  Convert object properties to camel case recursively.
@@ -44,11 +44,11 @@ const result: CamelCasedPropertiesDeep<UserWithFriends> = {
44
44
  @category Template literal
45
45
  @category Object
46
46
  */
47
- export type CamelCasedPropertiesDeep<Value> = Value extends Function
47
+ export type CamelCasedPropertiesDeep<Value, Options extends CamelCaseOptions = {preserveConsecutiveUppercase: true}> = Value extends Function
48
48
  ? Value
49
49
  : Value extends Array<infer U>
50
- ? Array<CamelCasedPropertiesDeep<U>>
50
+ ? Array<CamelCasedPropertiesDeep<U, Options>>
51
51
  : Value extends Set<infer U>
52
- ? Set<CamelCasedPropertiesDeep<U>> : {
53
- [K in keyof Value as CamelCase<K>]: CamelCasedPropertiesDeep<Value[K]>;
52
+ ? Set<CamelCasedPropertiesDeep<U, Options>> : {
53
+ [K in keyof Value as CamelCase<K, Options>]: CamelCasedPropertiesDeep<Value[K], Options>;
54
54
  };
@@ -1,4 +1,4 @@
1
- import type {CamelCase} from './camel-case';
1
+ import type {CamelCase, CamelCaseOptions} from './camel-case';
2
2
 
3
3
  /**
4
4
  Convert object properties to camel case but not recursively.
@@ -27,10 +27,10 @@ const result: CamelCasedProperties<User> = {
27
27
  @category Template literal
28
28
  @category Object
29
29
  */
30
- export type CamelCasedProperties<Value> = Value extends Function
30
+ export type CamelCasedProperties<Value, Options extends CamelCaseOptions = {preserveConsecutiveUppercase: true}> = Value extends Function
31
31
  ? Value
32
32
  : Value extends Array<infer U>
33
33
  ? Value
34
34
  : {
35
- [K in keyof Value as CamelCase<K>]: Value[K];
35
+ [K in keyof Value as CamelCase<K, Options>]: Value[K];
36
36
  };
@@ -1,9 +1,9 @@
1
1
  import type {UpperCaseCharacters, WordSeparators} from '../source/internal';
2
2
 
3
- // Transforms a string that is fully uppercase into a fully lowercase version. Needed to add support for SCREMAING_SNAKE_CASE, see https://github.com/sindresorhus/type-fest/issues/385
3
+ // Transforms a string that is fully uppercase into a fully lowercase version. Needed to add support for SCREAMING_SNAKE_CASE, see https://github.com/sindresorhus/type-fest/issues/385
4
4
  type UpperCaseToLowerCase<T extends string> = T extends Uppercase<T> ? Lowercase<T> : T;
5
5
 
6
- // This implemntation does not supports SCREMAING_SNAKE_CASE, it used internaly by `SplitIncludingDelimiters`.
6
+ // This implementation does not support SCREAMING_SNAKE_CASE, it is used internally by `SplitIncludingDelimiters`.
7
7
  type SplitIncludingDelimiters_<Source extends string, Delimiter extends string> =
8
8
  Source extends '' ? [] :
9
9
  Source extends `${infer FirstPart}${Delimiter}${infer SecondPart}` ?
@@ -19,7 +19,7 @@ Enforce optional keys (by adding the `?` operator) for keys that have a union wi
19
19
 
20
20
  @example
21
21
  ```
22
- import type {Merge} from 'type-fest';
22
+ import type {EnforceOptional} from 'type-fest';
23
23
 
24
24
  type Foo = {
25
25
  a: string;
@@ -6,7 +6,7 @@ type ArrayLengthMutationKeys = 'splice' | 'push' | 'pop' | 'shift' | 'unshift';
6
6
  /**
7
7
  Create a type that represents an array of the given type and length. The array's length and the `Array` prototype methods that manipulate its length are excluded in the resulting type.
8
8
 
9
- Please participate in [this issue](https://github.com/microsoft/TypeScript/issues/26223) if you want to have a similiar type built into TypeScript.
9
+ Please participate in [this issue](https://github.com/microsoft/TypeScript/issues/26223) if you want to have a similar type built into TypeScript.
10
10
 
11
11
  Use-cases:
12
12
  - Declaring fixed-length tuples or arrays with a large number of items.
@@ -1,4 +1,5 @@
1
1
  import type {Primitive} from './primitive';
2
+ import type {Simplify} from './simplify';
2
3
 
3
4
  /**
4
5
  Returns a boolean for whether the two given types are equal.
@@ -93,3 +94,93 @@ export type FirstArrayElement<TArray extends UnknownArrayOrTuple> = TArray exten
93
94
  Extracts the type of an array or tuple minus the first element.
94
95
  */
95
96
  export type ArrayTail<TArray extends UnknownArrayOrTuple> = TArray extends readonly [unknown, ...infer TTail] ? TTail : [];
97
+
98
+ /**
99
+ Returns a boolean for whether the string is lowercased.
100
+ */
101
+ export type IsLowerCase<T extends string> = T extends Lowercase<T> ? true : false;
102
+
103
+ /**
104
+ Returns a boolean for whether the string is uppercased.
105
+ */
106
+ export type IsUpperCase<T extends string> = T extends Uppercase<T> ? true : false;
107
+
108
+ /**
109
+ Returns a boolean for whether the string is numeric.
110
+ */
111
+ export type IsNumeric<T extends string> = T extends `${number}` ? true : false;
112
+
113
+ /**
114
+ Returns a boolean for whether the the type is `any`.
115
+
116
+ @link https://stackoverflow.com/a/49928360/1490091
117
+ */
118
+ export type IsAny<T> = 0 extends 1 & T ? true : false;
119
+
120
+ /**
121
+ For an object T, if it has any properties that are a union with `undefined`, make those into optional properties instead.
122
+
123
+ @example
124
+ ```
125
+ type User = {
126
+ firstName: string;
127
+ lastName: string | undefined;
128
+ };
129
+
130
+ type OptionalizedUser = UndefinedToOptional<User>;
131
+ //=> {
132
+ // firstName: string;
133
+ // lastName?: string;
134
+ // }
135
+ ```
136
+ */
137
+ export type UndefinedToOptional<T extends object> = Simplify<
138
+ {
139
+ // Property is not a union with `undefined`, keep it as-is.
140
+ [Key in keyof Pick<T, FilterDefinedKeys<T>>]: T[Key];
141
+ } & {
142
+ // Property _is_ a union with defined value. Set as optional (via `?`) and remove `undefined` from the union.
143
+ [Key in keyof Pick<T, FilterOptionalKeys<T>>]?: Exclude<T[Key], undefined>;
144
+ }
145
+ >;
146
+
147
+ // Returns `never` if the key or property is not jsonable without testing whether the property is required or optional otherwise return the key.
148
+ type BaseKeyFilter<Type, Key extends keyof Type> = Key extends symbol
149
+ ? never
150
+ : Type[Key] extends symbol
151
+ ? never
152
+ : [(...args: any[]) => any] extends [Type[Key]]
153
+ ? never
154
+ : Key;
155
+
156
+ /**
157
+ Returns the required keys.
158
+ */
159
+ type FilterDefinedKeys<T extends object> = Exclude<
160
+ {
161
+ [Key in keyof T]: IsAny<T[Key]> extends true
162
+ ? Key
163
+ : undefined extends T[Key]
164
+ ? never
165
+ : T[Key] extends undefined
166
+ ? never
167
+ : BaseKeyFilter<T, Key>;
168
+ }[keyof T],
169
+ undefined
170
+ >;
171
+
172
+ /**
173
+ Returns the optional keys.
174
+ */
175
+ type FilterOptionalKeys<T extends object> = Exclude<
176
+ {
177
+ [Key in keyof T]: IsAny<T[Key]> extends true
178
+ ? never
179
+ : undefined extends T[Key]
180
+ ? T[Key] extends undefined
181
+ ? never
182
+ : BaseKeyFilter<T, Key>
183
+ : never;
184
+ }[keyof T],
185
+ undefined
186
+ >;
package/source/join.d.ts CHANGED
@@ -23,8 +23,13 @@ const path: Join<[1, 2, 3], '.'> = [1, 2, 3].join('.');
23
23
  export type Join<
24
24
  Strings extends Array<string | number>,
25
25
  Delimiter extends string,
26
- > = Strings extends [] ? '' :
27
- Strings extends [string | number] ? `${Strings[0]}` :
28
- // @ts-expect-error `Rest` is inferred as `unknown` here: https://github.com/microsoft/TypeScript/issues/45281
29
- Strings extends [string | number, ...infer Rest] ? `${Strings[0]}${Delimiter}${Join<Rest, Delimiter>}` :
30
- string;
26
+ > = Strings extends []
27
+ ? ''
28
+ : Strings extends [string | number]
29
+ ? `${Strings[0]}`
30
+ : Strings extends [
31
+ string | number,
32
+ ...infer Rest extends Array<string | number>,
33
+ ]
34
+ ? `${Strings[0]}${Delimiter}${Join<Rest, Delimiter>}`
35
+ : string;
@@ -0,0 +1,37 @@
1
+ import type {JsonPrimitive, JsonValue} from './basic';
2
+
3
+ type JsonifiableObject = {[Key in string]?: Jsonifiable} | {toJSON: () => Jsonifiable};
4
+ type JsonifiableArray = readonly Jsonifiable[];
5
+
6
+ /**
7
+ Matches a value that can be losslessly converted to JSON.
8
+
9
+ Can be used to type values that you expect to pass to `JSON.stringify`.
10
+
11
+ `undefined` is allowed in object fields (for example, `{a?: number}`) as a special case even though `JSON.stringify({a: undefined})` is `{}` because it makes this class more widely useful and checking for undefined-but-present values is likely an anti-pattern.
12
+
13
+ @example
14
+ ```
15
+ import type {Jsonifiable} from 'type-fest';
16
+
17
+ // @ts-expect-error
18
+ const error: Jsonifiable = {
19
+ map: new Map([['a', 1]]),
20
+ };
21
+
22
+ JSON.stringify(error);
23
+ //=> {"map": {}}
24
+
25
+ const good: Jsonifiable = {
26
+ number: 3,
27
+ date: new Date(),
28
+ missing: undefined,
29
+ }
30
+
31
+ JSON.stringify(good);
32
+ //=> {"number": 3, "date": "2022-10-17T22:22:35.920Z"}
33
+ ```
34
+
35
+ @category JSON
36
+ */
37
+ export type Jsonifiable = JsonPrimitive | JsonifiableObject | JsonifiableArray;
@@ -1,31 +1,26 @@
1
1
  import type {JsonPrimitive, JsonValue} from './basic';
2
- import type {Merge} from './merge';
2
+ import type {EmptyObject} from './empty-object';
3
+ import type {IsAny, UndefinedToOptional} from './internal';
3
4
  import type {NegativeInfinity, PositiveInfinity} from './numeric';
4
5
  import type {TypedArray} from './typed-array';
5
6
 
6
7
  // Note: The return value has to be `any` and not `unknown` so it can match `void`.
7
8
  type NotJsonable = ((...args: any[]) => any) | undefined | symbol;
8
9
 
9
- // Returns never if the key or property is not jsonable without testing whether the property is required or optional otherwise return the key.
10
- type BaseKeyFilter<Type, Key extends keyof Type> = Key extends symbol
11
- ? never
12
- : Type[Key] extends symbol
13
- ? never
14
- : [(...args: any[]) => any] extends [Type[Key]]
15
- ? never
16
- : Key;
17
-
18
- // Returns never if the key or property is not jsonable or optional otherwise return the key.
19
- type RequiredKeyFilter<Type, Key extends keyof Type> = undefined extends Type[Key]
20
- ? never
21
- : BaseKeyFilter<Type, Key>;
22
-
23
- // Returns never if the key or property is not jsonable or required otherwise return the key.
24
- type OptionalKeyFilter<Type, Key extends keyof Type> = undefined extends Type[Key]
25
- ? Type[Key] extends undefined
26
- ? never
27
- : BaseKeyFilter<Type, Key>
28
- : never;
10
+ type JsonifyTuple<T extends [unknown, ...unknown[]]> = {
11
+ [Key in keyof T]: T[Key] extends NotJsonable ? null : Jsonify<T[Key]>;
12
+ };
13
+
14
+ type FilterJsonableKeys<T extends object> = {
15
+ [Key in keyof T]: T[Key] extends NotJsonable ? never : Key;
16
+ }[keyof T];
17
+
18
+ /**
19
+ JSON serialize objects (not including arrays) and classes.
20
+ */
21
+ type JsonifyObject<T extends object> = {
22
+ [Key in keyof Pick<T, FilterJsonableKeys<T>>]: Jsonify<T[Key]>;
23
+ };
29
24
 
30
25
  /**
31
26
  Transform a type to one that is assignable to the `JsonValue` type.
@@ -84,29 +79,36 @@ const timeJson = JSON.parse(JSON.stringify(time)) as Jsonify<typeof time>;
84
79
 
85
80
  @category JSON
86
81
  */
87
- export type Jsonify<T> =
88
- // Check if there are any non-JSONable types represented in the union.
89
- // Note: The use of tuples in this first condition side-steps distributive conditional types
90
- // (see https://github.com/microsoft/TypeScript/issues/29368#issuecomment-453529532)
91
- [Extract<T, NotJsonable | bigint>] extends [never]
92
- ? T extends PositiveInfinity | NegativeInfinity ? null
93
- : T extends JsonPrimitive ? T // Primitive is acceptable
94
- : T extends object
95
- // Any object with toJSON is special case
96
- ? T extends {toJSON(): infer J} ? (() => J) extends (() => JsonValue) // Is J assignable to JsonValue?
97
- ? J // Then T is Jsonable and its Jsonable value is J
98
- : never // Not Jsonable because its toJSON() method does not return JsonValue
99
- // Instanced primitives are objects
100
- : T extends Number ? number
101
- : T extends String ? string
102
- : T extends Boolean ? boolean
103
- : T extends Map<any, any> | Set<any> ? {}
104
- : T extends TypedArray ? Record<string, number>
105
- : T extends any[]
106
- ? {[I in keyof T]: T[I] extends NotJsonable ? null : Jsonify<T[I]>}
107
- : Merge<
108
- {[Key in keyof T as RequiredKeyFilter<T, Key>]: Jsonify<T[Key]>},
109
- {[Key in keyof T as OptionalKeyFilter<T, Key>]?: Jsonify<Exclude<T[Key], undefined>>}
110
- > // Recursive call for its children
111
- : never // Otherwise any other non-object is removed
112
- : never; // Otherwise non-JSONable type union was found not empty
82
+ export type Jsonify<T> = IsAny<T> extends true
83
+ ? any
84
+ : T extends PositiveInfinity | NegativeInfinity
85
+ ? null
86
+ : T extends JsonPrimitive
87
+ ? T
88
+ : // Instanced primitives are objects
89
+ T extends Number
90
+ ? number
91
+ : T extends String
92
+ ? string
93
+ : T extends Boolean
94
+ ? boolean
95
+ : T extends Map<any, any> | Set<any>
96
+ ? EmptyObject
97
+ : T extends TypedArray
98
+ ? Record<string, number>
99
+ : T extends NotJsonable
100
+ ? never // Non-JSONable type union was found not empty
101
+ : // Any object with toJSON is special case
102
+ T extends {toJSON(): infer J}
103
+ ? (() => J) extends () => JsonValue // Is J assignable to JsonValue?
104
+ ? J // Then T is Jsonable and its Jsonable value is J
105
+ : Jsonify<J> // Maybe if we look a level deeper we'll find a JsonValue
106
+ : T extends []
107
+ ? []
108
+ : T extends [unknown, ...unknown[]]
109
+ ? JsonifyTuple<T>
110
+ : T extends ReadonlyArray<infer U>
111
+ ? Array<U extends NotJsonable ? null : Jsonify<U>>
112
+ : T extends object
113
+ ? JsonifyObject<UndefinedToOptional<T>> // JsonifyObject recursive call for its children
114
+ : never; // Otherwise any other non-object is removed
@@ -13,7 +13,7 @@ import type {
13
13
  } from './internal';
14
14
 
15
15
  /**
16
- Deeply smplifies an object excluding iterables and functions. Used internally to improve the UX and accept both interfaces and type aliases as inputs.
16
+ Deeply simplifies an object excluding iterables and functions. Used internally to improve the UX and accept both interfaces and type aliases as inputs.
17
17
  */
18
18
  type SimplifyDeep<Type> = ConditionalSimplifyDeep<Type, Function | Iterable<unknown>, object>;
19
19
 
@@ -200,7 +200,7 @@ Merge mode for array/tuple elements.
200
200
  type ArrayMergeMode = 'spread' | 'replace';
201
201
 
202
202
  /**
203
- Test if it sould spread top-level arrays.
203
+ Test if it should spread top-level arrays.
204
204
  */
205
205
  type ShouldSpread<Options extends MergeDeepInternalOptions> = Options['spreadTopLevelArrays'] extends false
206
206
  ? Options['arrayMergeMode'] extends 'spread' ? true : false
@@ -8,7 +8,7 @@ declare global {
8
8
  /**
9
9
  @remarks
10
10
  The TC39 observable proposal defines a `closed` property, but some implementations (such as xstream) do not as of 10/08/2021.
11
- As well, some guideance on making an `Observable` do not include `closed` propery.
11
+ As well, some guidance on making an `Observable` to not include `closed` property.
12
12
  @see https://github.com/tc39/proposal-observable/blob/master/src/Observable.js#L129-L130
13
13
  @see https://github.com/staltz/xstream/blob/6c22580c1d84d69773ee4b0905df44ad464955b3/src/index.ts#L79-L85
14
14
  @see https://github.com/benlesh/symbol-observable#making-an-object-observable
@@ -240,7 +240,7 @@ declare namespace PackageJson {
240
240
  Import map entries of a module, optionally with conditions.
241
241
  */
242
242
  export type Imports = { // eslint-disable-line @typescript-eslint/consistent-indexed-object-style
243
- [key: string]: string | {[key in ExportCondition]: Exports};
243
+ [key: `#${string}`]: string | {[key in ExportCondition]: Exports};
244
244
  };
245
245
 
246
246
  // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
@@ -29,7 +29,6 @@ const userMaskSettings: UserMask = {
29
29
  firstname: 'show',
30
30
  lastname: 'mask',
31
31
  },
32
- phoneNumbers: 'mask',
33
32
  created: 'show',
34
33
  active: 'show',
35
34
  passwordHash: 'hide',
@@ -1,6 +1,3 @@
1
- import type {Except} from './except';
2
- import type {Simplify} from './simplify';
3
-
4
1
  /**
5
2
  Create a type that makes the given keys non-nullable, where the remaining keys are kept as is.
6
3
 
@@ -35,10 +32,8 @@ type AllNonNullable = SetNonNullable<Foo>;
35
32
 
36
33
  @category Object
37
34
  */
38
- export type SetNonNullable<BaseType, Keys extends keyof BaseType = keyof BaseType> =
39
- Simplify<
40
- // Pick just the keys that are readonly from the base type.
41
- Except<BaseType, Keys> &
42
- // Pick the keys that should be non-nullable from the base type and make them non-nullable.
43
- {[Key in Keys]: NonNullable<BaseType[Key]>}
44
- >;
35
+ export type SetNonNullable<BaseType, Keys extends keyof BaseType = keyof BaseType> = {
36
+ [Key in keyof BaseType]: Key extends Keys
37
+ ? NonNullable<BaseType[Key]>
38
+ : BaseType[Key];
39
+ };
@@ -1,4 +1,5 @@
1
- type IsAny<T> = 0 extends (1 & T) ? true : false; // https://stackoverflow.com/a/49928360/3406963
1
+ import type {IsAny} from './internal';
2
+
2
3
  type IsNever<T> = [T] extends [never] ? true : false;
3
4
  type IsUnknown<T> = IsNever<T> extends false ? T extends unknown ? unknown extends T ? IsAny<T> extends false ? true : false : false : false : false;
4
5
 
@@ -0,0 +1,57 @@
1
+ import type {IsLowerCase, IsNumeric, IsUpperCase, WordSeparators} from './internal';
2
+
3
+ type SkipEmptyWord<Word extends string> = Word extends '' ? [] : [Word];
4
+
5
+ type RemoveLastCharacter<Sentence extends string, Character extends string> = Sentence extends `${infer LeftSide}${Character}`
6
+ ? SkipEmptyWord<LeftSide>
7
+ : never;
8
+
9
+ /**
10
+ Split a string (almost) like Lodash's `_.words()` function.
11
+
12
+ - Split on each word that begins with a capital letter.
13
+ - Split on each {@link WordSeparators}.
14
+ - Split on numeric sequence.
15
+
16
+ @example
17
+ ```
18
+ type Words0 = SplitWords<'helloWorld'>; // ['hello', 'World']
19
+ type Words1 = SplitWords<'helloWORLD'>; // ['hello', 'WORLD']
20
+ type Words2 = SplitWords<'hello-world'>; // ['hello', 'world']
21
+ type Words3 = SplitWords<'--hello the_world'>; // ['hello', 'the', 'world']
22
+ type Words4 = SplitWords<'lifeIs42'>; // ['life', 'Is', '42']
23
+ ```
24
+
25
+ @internal
26
+ @category Change case
27
+ @category Template literal
28
+ */
29
+ export type SplitWords<
30
+ Sentence extends string,
31
+ LastCharacter extends string = '',
32
+ CurrentWord extends string = '',
33
+ > = Sentence extends `${infer FirstCharacter}${infer RemainingCharacters}`
34
+ ? FirstCharacter extends WordSeparators
35
+ // Skip word separator
36
+ ? [...SkipEmptyWord<CurrentWord>, ...SplitWords<RemainingCharacters, LastCharacter>]
37
+ : LastCharacter extends ''
38
+ // Fist char of word
39
+ ? SplitWords<RemainingCharacters, FirstCharacter, FirstCharacter>
40
+ // Case change: non-numeric to numeric, push word
41
+ : [false, true] extends [IsNumeric<LastCharacter>, IsNumeric<FirstCharacter>]
42
+ ? [...SkipEmptyWord<CurrentWord>, ...SplitWords<RemainingCharacters, FirstCharacter, FirstCharacter>]
43
+ // Case change: numeric to non-numeric, push word
44
+ : [true, false] extends [IsNumeric<LastCharacter>, IsNumeric<FirstCharacter>]
45
+ ? [...SkipEmptyWord<CurrentWord>, ...SplitWords<RemainingCharacters, FirstCharacter, FirstCharacter>]
46
+ // No case change: concat word
47
+ : [true, true] extends [IsNumeric<LastCharacter>, IsNumeric<FirstCharacter>]
48
+ ? SplitWords<RemainingCharacters, FirstCharacter, `${CurrentWord}${FirstCharacter}`>
49
+ // Case change: lower to upper, push word
50
+ : [true, true] extends [IsLowerCase<LastCharacter>, IsUpperCase<FirstCharacter>]
51
+ ? [...SkipEmptyWord<CurrentWord>, ...SplitWords<RemainingCharacters, FirstCharacter, FirstCharacter>]
52
+ // Case change: upper to lower, brings back the last character, push word
53
+ : [true, true] extends [IsUpperCase<LastCharacter>, IsLowerCase<FirstCharacter>]
54
+ ? [...RemoveLastCharacter<CurrentWord, LastCharacter>, ...SplitWords<RemainingCharacters, FirstCharacter, `${LastCharacter}${FirstCharacter}`>]
55
+ // No case change: concat word
56
+ : SplitWords<RemainingCharacters, FirstCharacter, `${CurrentWord}${FirstCharacter}`>
57
+ : [...SkipEmptyWord<CurrentWord>];
@@ -1,5 +1,5 @@
1
1
  /**
2
- Convert a tuple into a union type of its elements.
2
+ Convert a tuple/array into a union type of its elements.
3
3
 
4
4
  This can be useful when you have a fixed set of allowed values and want a type defining only the allowed values, but do not want to repeat yourself.
5
5
 
@@ -48,4 +48,4 @@ type NumberBool = typeof numberBool[number];
48
48
 
49
49
  @category Array
50
50
  */
51
- export type TupleToUnion<ArrayType> = ArrayType extends readonly [infer Head, ...(infer Rest)] ? Head | TupleToUnion<Rest> : never;
51
+ export type TupleToUnion<ArrayType> = ArrayType extends readonly unknown[] ? ArrayType[number] : never;