1 | import type { Middleware, StoreEnhancer } from 'redux'
|
2 | import type { Tuple } from './utils'
|
3 |
|
4 | export function safeAssign<T extends object>(
|
5 | target: T,
|
6 | ...args: Array<Partial<NoInfer<T>>>
|
7 | ) {
|
8 | Object.assign(target, ...args)
|
9 | }
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | export type IsAny<T, True, False = never> =
|
18 |
|
19 | true | false extends (T extends never ? true : false) ? True : False
|
20 |
|
21 | export type CastAny<T, CastTo> = IsAny<T, CastTo, T>
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | export type IsUnknown<T, True, False = never> = unknown extends T
|
30 | ? IsAny<T, False, True>
|
31 | : False
|
32 |
|
33 | export type FallbackIfUnknown<T, Fallback> = IsUnknown<T, Fallback, T>
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | export type IfMaybeUndefined<P, True, False> = [undefined] extends [P]
|
39 | ? True
|
40 | : False
|
41 |
|
42 |
|
43 |
|
44 |
|
45 | export type IfVoid<P, True, False> = [void] extends [P] ? True : False
|
46 |
|
47 |
|
48 |
|
49 |
|
50 | export type IsEmptyObj<T, True, False = never> = T extends any
|
51 | ? keyof T extends never
|
52 | ? IsUnknown<T, False, IfMaybeUndefined<T, False, IfVoid<T, False, True>>>
|
53 | : False
|
54 | : never
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | export type AtLeastTS35<True, False> = [True, False][IsUnknown<
|
65 | ReturnType<<T>() => T>,
|
66 | 0,
|
67 | 1
|
68 | >]
|
69 |
|
70 |
|
71 |
|
72 |
|
73 | export type IsUnknownOrNonInferrable<T, True, False> = AtLeastTS35<
|
74 | IsUnknown<T, True, False>,
|
75 | IsEmptyObj<T, True, IsUnknown<T, True, False>>
|
76 | >
|
77 |
|
78 |
|
79 |
|
80 |
|
81 | export type UnionToIntersection<U> = (
|
82 | U extends any ? (k: U) => void : never
|
83 | ) extends (k: infer I) => void
|
84 | ? I
|
85 | : never
|
86 |
|
87 |
|
88 | export type ExcludeFromTuple<T, E, Acc extends unknown[] = []> = T extends [
|
89 | infer Head,
|
90 | ...infer Tail,
|
91 | ]
|
92 | ? ExcludeFromTuple<Tail, E, [...Acc, ...([Head] extends [E] ? [] : [Head])]>
|
93 | : Acc
|
94 |
|
95 | type ExtractDispatchFromMiddlewareTuple<
|
96 | MiddlewareTuple extends readonly any[],
|
97 | Acc extends {},
|
98 | > = MiddlewareTuple extends [infer Head, ...infer Tail]
|
99 | ? ExtractDispatchFromMiddlewareTuple<
|
100 | Tail,
|
101 | Acc & (Head extends Middleware<infer D> ? IsAny<D, {}, D> : {})
|
102 | >
|
103 | : Acc
|
104 |
|
105 | export type ExtractDispatchExtensions<M> =
|
106 | M extends Tuple<infer MiddlewareTuple>
|
107 | ? ExtractDispatchFromMiddlewareTuple<MiddlewareTuple, {}>
|
108 | : M extends ReadonlyArray<Middleware>
|
109 | ? ExtractDispatchFromMiddlewareTuple<[...M], {}>
|
110 | : never
|
111 |
|
112 | type ExtractStoreExtensionsFromEnhancerTuple<
|
113 | EnhancerTuple extends readonly any[],
|
114 | Acc extends {},
|
115 | > = EnhancerTuple extends [infer Head, ...infer Tail]
|
116 | ? ExtractStoreExtensionsFromEnhancerTuple<
|
117 | Tail,
|
118 | Acc & (Head extends StoreEnhancer<infer Ext> ? IsAny<Ext, {}, Ext> : {})
|
119 | >
|
120 | : Acc
|
121 |
|
122 | export type ExtractStoreExtensions<E> =
|
123 | E extends Tuple<infer EnhancerTuple>
|
124 | ? ExtractStoreExtensionsFromEnhancerTuple<EnhancerTuple, {}>
|
125 | : E extends ReadonlyArray<StoreEnhancer>
|
126 | ? UnionToIntersection<
|
127 | E[number] extends StoreEnhancer<infer Ext>
|
128 | ? Ext extends {}
|
129 | ? IsAny<Ext, {}, Ext>
|
130 | : {}
|
131 | : {}
|
132 | >
|
133 | : never
|
134 |
|
135 | type ExtractStateExtensionsFromEnhancerTuple<
|
136 | EnhancerTuple extends readonly any[],
|
137 | Acc extends {},
|
138 | > = EnhancerTuple extends [infer Head, ...infer Tail]
|
139 | ? ExtractStateExtensionsFromEnhancerTuple<
|
140 | Tail,
|
141 | Acc &
|
142 | (Head extends StoreEnhancer<any, infer StateExt>
|
143 | ? IsAny<StateExt, {}, StateExt>
|
144 | : {})
|
145 | >
|
146 | : Acc
|
147 |
|
148 | export type ExtractStateExtensions<E> =
|
149 | E extends Tuple<infer EnhancerTuple>
|
150 | ? ExtractStateExtensionsFromEnhancerTuple<EnhancerTuple, {}>
|
151 | : E extends ReadonlyArray<StoreEnhancer>
|
152 | ? UnionToIntersection<
|
153 | E[number] extends StoreEnhancer<any, infer StateExt>
|
154 | ? StateExt extends {}
|
155 | ? IsAny<StateExt, {}, StateExt>
|
156 | : {}
|
157 | : {}
|
158 | >
|
159 | : never
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 | export type NoInfer<T> = [T][T extends any ? 0 : never]
|
169 |
|
170 | export type NonUndefined<T> = T extends undefined ? never : T
|
171 |
|
172 | export type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
|
173 |
|
174 | export type WithRequiredProp<T, K extends keyof T> = Omit<T, K> &
|
175 | Required<Pick<T, K>>
|
176 |
|
177 | export type WithOptionalProp<T, K extends keyof T> = Omit<T, K> &
|
178 | Partial<Pick<T, K>>
|
179 |
|
180 | export interface TypeGuard<T> {
|
181 | (value: any): value is T
|
182 | }
|
183 |
|
184 | export interface HasMatchFunction<T> {
|
185 | match: TypeGuard<T>
|
186 | }
|
187 |
|
188 | export const hasMatchFunction = <T>(
|
189 | v: Matcher<T>,
|
190 | ): v is HasMatchFunction<T> => {
|
191 | return v && typeof (v as HasMatchFunction<T>).match === 'function'
|
192 | }
|
193 |
|
194 |
|
195 | export type Matcher<T> = HasMatchFunction<T> | TypeGuard<T>
|
196 |
|
197 |
|
198 | export type ActionFromMatcher<M extends Matcher<any>> =
|
199 | M extends Matcher<infer T> ? T : never
|
200 |
|
201 | export type Id<T> = { [K in keyof T]: T[K] } & {}
|
202 |
|
203 | export type Tail<T extends any[]> = T extends [any, ...infer Tail]
|
204 | ? Tail
|
205 | : never
|
206 |
|
207 | export type UnknownIfNonSpecific<T> = {} extends T ? unknown : T
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 | export type SafePromise<T> = Promise<T> & {
|
214 | __linterBrands: 'SafePromise'
|
215 | }
|
216 |
|
217 |
|
218 |
|
219 |
|
220 | export function asSafePromise<Resolved, Rejected>(
|
221 | promise: Promise<Resolved>,
|
222 | fallback: (error: unknown) => Rejected,
|
223 | ) {
|
224 | return promise.catch(fallback) as SafePromise<Resolved | Rejected>
|
225 | }
|