lay-sing 0.2.0 → 0.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.
Files changed (282) hide show
  1. package/README.md +64 -29
  2. package/esm/{test-utils → main}/expect.d.ts +79 -9
  3. package/esm/main/expect.d.ts.map +1 -0
  4. package/esm/main/expect.js.map +1 -0
  5. package/esm/main/index.d.ts +29 -11
  6. package/esm/main/index.d.ts.map +1 -1
  7. package/esm/main/index.js +10 -13
  8. package/esm/main/index.js.map +1 -1
  9. package/esm/main/noop.d.ts +27 -0
  10. package/esm/main/noop.d.ts.map +1 -0
  11. package/esm/{test-utils/index.js → main/noop.js} +1 -8
  12. package/esm/main/noop.js.map +1 -0
  13. package/esm/utils/compare/assignable.d.ts +30 -0
  14. package/esm/utils/compare/assignable.d.ts.map +1 -0
  15. package/esm/utils/compare/assignable.js +2 -0
  16. package/esm/utils/compare/assignable.js.map +1 -0
  17. package/esm/utils/compare/exact.d.ts +50 -0
  18. package/esm/utils/compare/exact.d.ts.map +1 -0
  19. package/esm/utils/compare/exact.js +2 -0
  20. package/esm/utils/compare/exact.js.map +1 -0
  21. package/esm/utils/compare/extends.d.ts +46 -0
  22. package/esm/utils/compare/extends.d.ts.map +1 -0
  23. package/esm/utils/compare/extends.js +2 -0
  24. package/esm/utils/compare/extends.js.map +1 -0
  25. package/esm/utils/compare/index.d.ts +5 -0
  26. package/esm/utils/compare/index.d.ts.map +1 -0
  27. package/esm/utils/compare/index.js +7 -0
  28. package/esm/utils/compare/index.js.map +1 -0
  29. package/esm/utils/compare/overlap.d.ts +47 -0
  30. package/esm/utils/compare/overlap.d.ts.map +1 -0
  31. package/esm/utils/compare/overlap.js +2 -0
  32. package/esm/utils/compare/overlap.js.map +1 -0
  33. package/esm/utils/index.d.ts +10 -0
  34. package/esm/utils/index.d.ts.map +1 -0
  35. package/esm/utils/index.js +12 -0
  36. package/esm/utils/index.js.map +1 -0
  37. package/esm/utils/logic/assert.d.ts +18 -0
  38. package/esm/utils/logic/assert.d.ts.map +1 -0
  39. package/esm/utils/logic/assert.js +2 -0
  40. package/esm/utils/logic/assert.js.map +1 -0
  41. package/esm/utils/logic/if.d.ts +37 -0
  42. package/esm/utils/logic/if.d.ts.map +1 -0
  43. package/esm/utils/logic/if.js +2 -0
  44. package/esm/utils/logic/if.js.map +1 -0
  45. package/esm/utils/logic/index.d.ts +4 -0
  46. package/esm/utils/logic/index.d.ts.map +1 -0
  47. package/esm/utils/logic/index.js +6 -0
  48. package/esm/utils/logic/index.js.map +1 -0
  49. package/esm/utils/logic/switch.d.ts +87 -0
  50. package/esm/utils/logic/switch.d.ts.map +1 -0
  51. package/esm/utils/logic/switch.js +2 -0
  52. package/esm/utils/logic/switch.js.map +1 -0
  53. package/esm/utils/object/index.d.ts +4 -0
  54. package/esm/utils/object/index.d.ts.map +1 -0
  55. package/esm/utils/object/index.js +6 -0
  56. package/esm/utils/object/index.js.map +1 -0
  57. package/{script/main/key.d.ts → esm/utils/object/keys.d.ts} +40 -38
  58. package/esm/utils/object/keys.d.ts.map +1 -0
  59. package/esm/utils/object/keys.js +2 -0
  60. package/esm/utils/object/keys.js.map +1 -0
  61. package/esm/utils/object/pick.d.ts +16 -0
  62. package/esm/utils/object/pick.d.ts.map +1 -0
  63. package/esm/utils/object/pick.js +2 -0
  64. package/esm/utils/object/pick.js.map +1 -0
  65. package/esm/utils/object/props.d.ts +17 -0
  66. package/esm/utils/object/props.d.ts.map +1 -0
  67. package/esm/utils/object/props.js +2 -0
  68. package/esm/utils/object/props.js.map +1 -0
  69. package/esm/utils/tuple/append.d.ts +17 -0
  70. package/esm/utils/tuple/append.d.ts.map +1 -0
  71. package/esm/utils/tuple/append.js +2 -0
  72. package/esm/utils/tuple/append.js.map +1 -0
  73. package/esm/utils/tuple/concat.d.ts +31 -0
  74. package/esm/utils/tuple/concat.d.ts.map +1 -0
  75. package/esm/utils/tuple/concat.js +2 -0
  76. package/esm/utils/tuple/concat.js.map +1 -0
  77. package/esm/utils/tuple/includes.d.ts +20 -0
  78. package/esm/utils/tuple/includes.d.ts.map +1 -0
  79. package/esm/utils/tuple/includes.js +2 -0
  80. package/esm/utils/tuple/includes.js.map +1 -0
  81. package/esm/utils/tuple/index.d.ts +4 -0
  82. package/esm/utils/tuple/index.d.ts.map +1 -0
  83. package/esm/utils/tuple/index.js +6 -0
  84. package/esm/utils/tuple/index.js.map +1 -0
  85. package/package.json +5 -5
  86. package/script/{test-utils → main}/expect.d.ts +79 -9
  87. package/script/main/expect.d.ts.map +1 -0
  88. package/script/main/expect.js.map +1 -0
  89. package/script/main/index.d.ts +29 -11
  90. package/script/main/index.d.ts.map +1 -1
  91. package/script/main/index.js +13 -27
  92. package/script/main/index.js.map +1 -1
  93. package/script/main/noop.d.ts +27 -0
  94. package/script/main/noop.d.ts.map +1 -0
  95. package/script/{test-utils/index.js → main/noop.js} +1 -10
  96. package/script/main/noop.js.map +1 -0
  97. package/script/utils/compare/assignable.d.ts +30 -0
  98. package/script/utils/compare/assignable.d.ts.map +1 -0
  99. package/script/utils/compare/assignable.js +3 -0
  100. package/script/utils/compare/assignable.js.map +1 -0
  101. package/script/utils/compare/exact.d.ts +50 -0
  102. package/script/utils/compare/exact.d.ts.map +1 -0
  103. package/script/{main/async.js → utils/compare/exact.js} +1 -1
  104. package/script/utils/compare/exact.js.map +1 -0
  105. package/script/utils/compare/extends.d.ts +46 -0
  106. package/script/utils/compare/extends.d.ts.map +1 -0
  107. package/script/{main/boolean.js → utils/compare/extends.js} +1 -1
  108. package/script/utils/compare/extends.js.map +1 -0
  109. package/script/utils/compare/index.d.ts +5 -0
  110. package/script/utils/compare/index.d.ts.map +1 -0
  111. package/script/utils/compare/index.js +23 -0
  112. package/script/utils/compare/index.js.map +1 -0
  113. package/script/utils/compare/overlap.d.ts +47 -0
  114. package/script/utils/compare/overlap.d.ts.map +1 -0
  115. package/script/{main/control.js → utils/compare/overlap.js} +1 -1
  116. package/script/utils/compare/overlap.js.map +1 -0
  117. package/script/utils/index.d.ts +10 -0
  118. package/script/utils/index.d.ts.map +1 -0
  119. package/script/utils/index.js +28 -0
  120. package/script/utils/index.js.map +1 -0
  121. package/script/utils/logic/assert.d.ts +18 -0
  122. package/script/utils/logic/assert.d.ts.map +1 -0
  123. package/script/utils/logic/assert.js +3 -0
  124. package/script/utils/logic/assert.js.map +1 -0
  125. package/script/utils/logic/if.d.ts +37 -0
  126. package/script/utils/logic/if.d.ts.map +1 -0
  127. package/script/{main/type/set.js → utils/logic/if.js} +1 -1
  128. package/script/utils/logic/if.js.map +1 -0
  129. package/script/utils/logic/index.d.ts +4 -0
  130. package/script/utils/logic/index.d.ts.map +1 -0
  131. package/script/utils/logic/index.js +22 -0
  132. package/script/utils/logic/index.js.map +1 -0
  133. package/script/utils/logic/switch.d.ts +87 -0
  134. package/script/utils/logic/switch.d.ts.map +1 -0
  135. package/script/utils/logic/switch.js +3 -0
  136. package/script/utils/logic/switch.js.map +1 -0
  137. package/script/utils/object/index.d.ts +4 -0
  138. package/script/utils/object/index.d.ts.map +1 -0
  139. package/script/{main/type → utils/object}/index.js +3 -2
  140. package/script/utils/object/index.js.map +1 -0
  141. package/{esm/main/key.d.ts → script/utils/object/keys.d.ts} +40 -38
  142. package/script/utils/object/keys.d.ts.map +1 -0
  143. package/script/{main/json.js → utils/object/keys.js} +1 -1
  144. package/script/utils/object/keys.js.map +1 -0
  145. package/script/utils/object/pick.d.ts +16 -0
  146. package/script/utils/object/pick.d.ts.map +1 -0
  147. package/script/{main/key.js → utils/object/pick.js} +1 -1
  148. package/script/utils/object/pick.js.map +1 -0
  149. package/script/utils/object/props.d.ts +17 -0
  150. package/script/utils/object/props.d.ts.map +1 -0
  151. package/script/{main/doc.js → utils/object/props.js} +1 -1
  152. package/script/utils/object/props.js.map +1 -0
  153. package/script/utils/tuple/append.d.ts +17 -0
  154. package/script/utils/tuple/append.d.ts.map +1 -0
  155. package/script/utils/tuple/append.js +3 -0
  156. package/script/utils/tuple/append.js.map +1 -0
  157. package/script/utils/tuple/concat.d.ts +31 -0
  158. package/script/utils/tuple/concat.d.ts.map +1 -0
  159. package/script/utils/tuple/concat.js +3 -0
  160. package/script/utils/tuple/concat.js.map +1 -0
  161. package/script/utils/tuple/includes.d.ts +20 -0
  162. package/script/utils/tuple/includes.d.ts.map +1 -0
  163. package/script/utils/tuple/includes.js +3 -0
  164. package/script/utils/tuple/includes.js.map +1 -0
  165. package/script/utils/tuple/index.d.ts +4 -0
  166. package/script/utils/tuple/index.d.ts.map +1 -0
  167. package/script/utils/tuple/index.js +22 -0
  168. package/script/utils/tuple/index.js.map +1 -0
  169. package/esm/main/async.d.ts +0 -5
  170. package/esm/main/async.d.ts.map +0 -1
  171. package/esm/main/async.js +0 -2
  172. package/esm/main/async.js.map +0 -1
  173. package/esm/main/boolean.d.ts +0 -35
  174. package/esm/main/boolean.d.ts.map +0 -1
  175. package/esm/main/boolean.js +0 -2
  176. package/esm/main/boolean.js.map +0 -1
  177. package/esm/main/control.d.ts +0 -83
  178. package/esm/main/control.d.ts.map +0 -1
  179. package/esm/main/control.js +0 -2
  180. package/esm/main/control.js.map +0 -1
  181. package/esm/main/doc.d.ts +0 -30
  182. package/esm/main/doc.d.ts.map +0 -1
  183. package/esm/main/doc.js +0 -2
  184. package/esm/main/doc.js.map +0 -1
  185. package/esm/main/function.d.ts +0 -19
  186. package/esm/main/function.d.ts.map +0 -1
  187. package/esm/main/function.js +0 -3
  188. package/esm/main/function.js.map +0 -1
  189. package/esm/main/json.d.ts +0 -44
  190. package/esm/main/json.d.ts.map +0 -1
  191. package/esm/main/json.js +0 -2
  192. package/esm/main/json.js.map +0 -1
  193. package/esm/main/key.d.ts.map +0 -1
  194. package/esm/main/key.js +0 -2
  195. package/esm/main/key.js.map +0 -1
  196. package/esm/main/object.d.ts +0 -95
  197. package/esm/main/object.d.ts.map +0 -1
  198. package/esm/main/object.js +0 -2
  199. package/esm/main/object.js.map +0 -1
  200. package/esm/main/tuple.d.ts +0 -40
  201. package/esm/main/tuple.d.ts.map +0 -1
  202. package/esm/main/tuple.js +0 -2
  203. package/esm/main/tuple.js.map +0 -1
  204. package/esm/main/type/compare.d.ts +0 -79
  205. package/esm/main/type/compare.d.ts.map +0 -1
  206. package/esm/main/type/compare.js +0 -2
  207. package/esm/main/type/compare.js.map +0 -1
  208. package/esm/main/type/index.d.ts +0 -3
  209. package/esm/main/type/index.d.ts.map +0 -1
  210. package/esm/main/type/index.js +0 -5
  211. package/esm/main/type/index.js.map +0 -1
  212. package/esm/main/type/set.d.ts +0 -27
  213. package/esm/main/type/set.d.ts.map +0 -1
  214. package/esm/main/type/set.js +0 -2
  215. package/esm/main/type/set.js.map +0 -1
  216. package/esm/main/typed-array.d.ts +0 -5
  217. package/esm/main/typed-array.d.ts.map +0 -1
  218. package/esm/main/typed-array.js +0 -2
  219. package/esm/main/typed-array.js.map +0 -1
  220. package/esm/test-utils/compare.d.ts +0 -69
  221. package/esm/test-utils/compare.d.ts.map +0 -1
  222. package/esm/test-utils/compare.js +0 -2
  223. package/esm/test-utils/compare.js.map +0 -1
  224. package/esm/test-utils/expect.d.ts.map +0 -1
  225. package/esm/test-utils/expect.js.map +0 -1
  226. package/esm/test-utils/index.d.ts +0 -72
  227. package/esm/test-utils/index.d.ts.map +0 -1
  228. package/esm/test-utils/index.js.map +0 -1
  229. package/script/main/async.d.ts +0 -5
  230. package/script/main/async.d.ts.map +0 -1
  231. package/script/main/async.js.map +0 -1
  232. package/script/main/boolean.d.ts +0 -35
  233. package/script/main/boolean.d.ts.map +0 -1
  234. package/script/main/boolean.js.map +0 -1
  235. package/script/main/control.d.ts +0 -83
  236. package/script/main/control.d.ts.map +0 -1
  237. package/script/main/control.js.map +0 -1
  238. package/script/main/doc.d.ts +0 -30
  239. package/script/main/doc.d.ts.map +0 -1
  240. package/script/main/doc.js.map +0 -1
  241. package/script/main/function.d.ts +0 -19
  242. package/script/main/function.d.ts.map +0 -1
  243. package/script/main/function.js +0 -4
  244. package/script/main/function.js.map +0 -1
  245. package/script/main/json.d.ts +0 -44
  246. package/script/main/json.d.ts.map +0 -1
  247. package/script/main/json.js.map +0 -1
  248. package/script/main/key.d.ts.map +0 -1
  249. package/script/main/key.js.map +0 -1
  250. package/script/main/object.d.ts +0 -95
  251. package/script/main/object.d.ts.map +0 -1
  252. package/script/main/object.js +0 -3
  253. package/script/main/object.js.map +0 -1
  254. package/script/main/tuple.d.ts +0 -40
  255. package/script/main/tuple.d.ts.map +0 -1
  256. package/script/main/tuple.js +0 -3
  257. package/script/main/tuple.js.map +0 -1
  258. package/script/main/type/compare.d.ts +0 -79
  259. package/script/main/type/compare.d.ts.map +0 -1
  260. package/script/main/type/compare.js +0 -3
  261. package/script/main/type/compare.js.map +0 -1
  262. package/script/main/type/index.d.ts +0 -3
  263. package/script/main/type/index.d.ts.map +0 -1
  264. package/script/main/type/index.js.map +0 -1
  265. package/script/main/type/set.d.ts +0 -27
  266. package/script/main/type/set.d.ts.map +0 -1
  267. package/script/main/type/set.js.map +0 -1
  268. package/script/main/typed-array.d.ts +0 -5
  269. package/script/main/typed-array.d.ts.map +0 -1
  270. package/script/main/typed-array.js +0 -3
  271. package/script/main/typed-array.js.map +0 -1
  272. package/script/test-utils/compare.d.ts +0 -69
  273. package/script/test-utils/compare.d.ts.map +0 -1
  274. package/script/test-utils/compare.js +0 -3
  275. package/script/test-utils/compare.js.map +0 -1
  276. package/script/test-utils/expect.d.ts.map +0 -1
  277. package/script/test-utils/expect.js.map +0 -1
  278. package/script/test-utils/index.d.ts +0 -72
  279. package/script/test-utils/index.d.ts.map +0 -1
  280. package/script/test-utils/index.js.map +0 -1
  281. /package/esm/{test-utils → main}/expect.js +0 -0
  282. /package/script/{test-utils → main}/expect.js +0 -0
package/README.md CHANGED
@@ -22,32 +22,64 @@ expect<never>().toBe<'should fail'>().success
22
22
  >
23
23
  > I know this library is quite simple and serves a specific purpose, so one of its API design principles is to minimize the cognitive load for users. You just need to remember to **start with an `expect<>()` call** and **end with some property access**. Leave the rest to editor suggestions and inline documentation.
24
24
 
25
- ## Install
25
+ ## Install & Import
26
26
 
27
- ### [NPM](https://www.npmjs.com/package/lay-sing)
27
+ <details>
28
+ <summary>NPM</summary>
28
29
 
29
30
  ```sh
30
31
  npm i -D lay-sing
31
32
  ```
32
33
 
33
34
  ```ts
34
- import type { Exact } from 'lay-sing'
35
- import { expect } from 'lay-sing/test-utils'
35
+ import { expect } from 'lay-sing'
36
36
  ```
37
37
 
38
- > This library is also published to [JSR (`@leawind/lay-sing`)](https://jsr.io/@leawind/lay-sing)
38
+ </details>
39
+
40
+ <details>
41
+ <summary>Deno</summary>
42
+
43
+ ### From NPM
44
+
45
+ ```sh
46
+ deno add npm:lay-sing
47
+ ```
48
+
49
+ ```ts
50
+ import { expect } from 'lay-sing'
51
+ ```
52
+
53
+ ### From JSR
54
+
55
+ This library is also published to [JSR (`@leawind/lay-sing`)](https://jsr.io/@leawind/lay-sing)
56
+
57
+ ```sh
58
+ deno add @leawind/lay-sing
59
+ ```
60
+
61
+ ```ts
62
+ import { expect } from '@leawind/lay-sing'
63
+ ```
64
+
65
+ ### From Latest commit
66
+
67
+ ```ts
68
+ import { expect } from 'https://raw.githubusercontent.com/Leawind/lay-sing/refs/heads/main/src/main/index.ts'
69
+ import { Exact } from 'https://raw.githubusercontent.com/Leawind/lay-sing/refs/heads/main/src/utils/index.ts'
70
+ ```
71
+
72
+ </details>
39
73
 
40
74
  ---
41
75
 
42
76
  ## Usage
43
77
 
44
- ### Testing Utilities
45
-
46
78
  ```ts
47
- import { compare, expect, NOOP } from 'lay-sing/test-utils'
79
+ import { expect } from 'lay-sing'
48
80
  ```
49
81
 
50
- The `test-utils` module provides utilities for **compile-time** type validation. These utilities have **no runtime impact** — they always return a special [`NOOP`](https://jsr.io/@leawind/lay-sing/doc/test-utils/~/NOOP) value that safely supports almost any property access or method call.
82
+ The main module provides utilities for **compile-time** type validation. These utilities have **no runtime impact** — they always return a special [`NOOP`](https://jsr.io/@leawind/lay-sing/doc/~/NOOP) value that safely supports almost any property access or method call.
51
83
 
52
84
  A typical type test statement follows this pattern:
53
85
 
@@ -73,22 +105,27 @@ At runtime, the function always returns the `NOOP` object, which performs **no o
73
105
  #### Common Usage
74
106
 
75
107
  ```ts
76
- // Exact equality
77
- expect<A>().toBe<B>().success // Passes only if A and B are identical
108
+ // Passes only if A and B are identical
109
+ expect<keyof { a: 2 }>().toBe<'a'>().success
78
110
 
79
- // Subtype check
80
- expect<A>().toExtend<B>().success // Passes if A extends B
111
+ // Passes if A extends B
112
+ expect<12138>().toExtend<number>().success
81
113
 
82
- // Property existence
114
+ // Passes if mutually assignable
115
+ expect<{ a: 1; b: 2 }>().toEqual<{ a: 1 } & { b: 2 }>().success
116
+
117
+ // Test property existence
83
118
  expect<{ name: string }>().toHaveKey<'name'>().success
119
+ ```
84
120
 
85
- // Primitive checks
86
- expect<true>().toBeTrue.success
87
- expect<'hello'>().toExtendString.success
121
+ Aliases:
88
122
 
89
- // Type comparison
90
- compare<A, B>().same // Available only if A ≡ B
91
- compare<A, B>().different // Available only if A ≠ B
123
+ ```ts
124
+ expect<never>().toBe<never>().success
125
+ expect<never>().toBeNever
126
+
127
+ expect<'hello'>().toExtend<string>().success
128
+ expect<'hello'>().toExtendString
92
129
  ```
93
130
 
94
131
  #### NOOP
@@ -109,15 +146,18 @@ await NOOP // Does not await (not thenable)
109
146
 
110
147
  ### Type Tools
111
148
 
112
- The main entry point provides some utility types for common type-level programming tasks. All types are flat-exported from the main entry point — no need to import from nested paths.
149
+ It provides some utility types organized into categories for common type-level programming tasks. These can be imported from the `lay-sing/utils` entry point.
113
150
 
114
151
  ```ts
115
- import type { Exact } from 'lay-sing'
152
+ import type { Exact, Extends, Overlap } from 'lay-sing/utils'
116
153
  ```
117
154
 
118
155
  ### Examples
119
156
 
120
157
  ```typescript
158
+ // Import the utility types
159
+ import type { ConcatTuple, Exact, If, KeysOfBaseType } from '@leawind/lay-sing/utils'
160
+
121
161
  // Test if exactly the same
122
162
  type False = Exact<{ a: 1 }, { a?: 1 }> // false
123
163
  type Yes = Exact<boolean, true | false, 'yes', 'no'> // 'yes'
@@ -125,15 +165,10 @@ type Yes = Exact<boolean, true | false, 'yes', 'no'> // 'yes'
125
165
  // Conditional Types
126
166
  type Result = If<true, 'yes', 'no'> // 'yes'
127
167
 
128
- // Boolean Logic
129
- type IsTrue = And<true, true> // true
168
+ type FailResult = If<Exact<number, string>, 'yes', 'no'> // 'no'
130
169
 
131
170
  // Tuple Manipulation
132
171
  type Combined = ConcatTuple<[1, 2], [3, 4]> // [1, 2, 3, 4]
133
172
 
134
- // Object Utilities
135
- type PartialObj = DeepPartial<{ a: string; nested: { b: number } }>
136
- // { a?: string; nested?: { b?: number } }
173
+ type UniqueCombined = ConcatUniqueTuple<[1, 2], [2, 3]> // [1, 2, 3]
137
174
  ```
138
-
139
- [Full API documentation is available on JSR](https://jsr.io/@leawind/lay-sing/doc)
@@ -1,4 +1,4 @@
1
- import type { Exact, Extends, If, IfTupleIncludes, ProperExtend, SafePick } from '../main/index.js';
1
+ import type { Exact, Extends, If, IfTupleIncludes, MutuallyAssignable, ProperExtend, SafePick } from '../utils/index.js';
2
2
  /**
3
3
  * Represents the result of a type assertion based on a boolean condition.
4
4
  *
@@ -32,12 +32,36 @@ type ExpectTypeMethods<T, H extends PropertyKey = never> = {
32
32
  *
33
33
  * @example
34
34
  * ```ts
35
+ * import { expect } from '@leawind/lay-sing'
36
+ *
35
37
  * expect<any>().toBe<any>().success
36
38
  * expect<never>().toBe<never>().success
37
39
  * expect<false>().toBe<true>().fail
38
40
  * ```
39
41
  */
40
- toBe<U>(): TypeAssertionResult<Exact<T, U>>;
42
+ toBe<U>(): TypeAssertionResult<Exact<T, U>, ExpectType<T, H>>;
43
+ toBe<U>(_: U): TypeAssertionResult<Exact<T, U>, ExpectType<T, H>>;
44
+ /**
45
+ * Tests if the current type is mutually assignable with the provided type U.
46
+ *
47
+ * It's like:
48
+ *
49
+ * ```ts ignore
50
+ * [T] extends [U] ? [U] extends [T] ? Yes : No : No
51
+ * ```
52
+ *
53
+ * @template U The type to compare with
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * import { expect } from '@leawind/lay-sing'
58
+ *
59
+ * expect<{ a: 1; b: 2 }>().toEqual<{ a: 1 } & { b: 2 }>().success
60
+ * expect<1>().toEqual<1 | 2>().fail
61
+ * ```
62
+ */
63
+ toEqual<U>(): TypeAssertionResult<MutuallyAssignable<T, U>, ExpectType<T, H>>;
64
+ toEqual<U>(_: U): TypeAssertionResult<MutuallyAssignable<T, U>, ExpectType<T, H>>;
41
65
  /**
42
66
  * Tests if the current type T extends the provided type U.
43
67
  *
@@ -45,12 +69,15 @@ type ExpectTypeMethods<T, H extends PropertyKey = never> = {
45
69
  *
46
70
  * @example
47
71
  * ```ts
72
+ * import { expect } from '@leawind/lay-sing'
73
+ *
48
74
  * expect<3.14>().toExtend<number>().success
49
75
  * expect<2>().toExtend<string>().fail
50
76
  * expect<'hello'>().toExtend<string>().success
51
77
  * ```
52
78
  */
53
- toExtend<U>(): TypeAssertionResult<Extends<T, U>>;
79
+ toExtend<U>(): TypeAssertionResult<Extends<T, U>, ExpectType<T, H>>;
80
+ toExtend<U>(_: U): TypeAssertionResult<Extends<T, U>, ExpectType<T, H>>;
54
81
  /**
55
82
  * Tests if the current type T properly extends the provided type U (extends but is not the same).
56
83
  *
@@ -58,12 +85,15 @@ type ExpectTypeMethods<T, H extends PropertyKey = never> = {
58
85
  *
59
86
  * @example
60
87
  * ```ts
88
+ * import { expect } from '@leawind/lay-sing'
89
+ *
61
90
  * expect<2>().toProperExtend<number>().success
62
91
  * expect<'a' | 'b'>().toProperExtend<string>().success
63
92
  * expect<number>().toProperExtend<number>().fail
64
93
  * ```
65
94
  */
66
- toProperExtend<U>(): TypeAssertionResult<ProperExtend<T, U>>;
95
+ toProperExtend<U>(): TypeAssertionResult<ProperExtend<T, U>, ExpectType<T, H>>;
96
+ toProperExtend<U>(_: U): TypeAssertionResult<ProperExtend<T, U>, ExpectType<T, H>>;
67
97
  /**
68
98
  * Tests if the current type `T` has a property with key `K`.
69
99
  *
@@ -77,6 +107,8 @@ type ExpectTypeMethods<T, H extends PropertyKey = never> = {
77
107
  * ### Examples
78
108
  *
79
109
  * ```ts
110
+ * import { expect } from '@leawind/lay-sing'
111
+ *
80
112
  * type WithProp = { prop: string; another: number; may?: 5 }
81
113
  *
82
114
  * // Single key checks
@@ -88,8 +120,22 @@ type ExpectTypeMethods<T, H extends PropertyKey = never> = {
88
120
  * expect<WithProp>().toHaveKey<'may' | 'unexist'>().fail
89
121
  * ```
90
122
  */
91
- toHaveKey<K extends PropertyKey>(): IfTupleIncludes<[never, any], K, never, TypeAssertionResult<Extends<K, keyof T>>>;
123
+ toHaveKey<K extends PropertyKey>(): IfTupleIncludes<[
124
+ never,
125
+ any
126
+ ], K, never, TypeAssertionResult<Extends<K, keyof T>, ExpectType<T, H>>>;
127
+ toHaveKey<K extends PropertyKey>(_: K): IfTupleIncludes<[
128
+ never,
129
+ any
130
+ ], K, never, TypeAssertionResult<Extends<K, keyof T>, ExpectType<T, H>>>;
92
131
  };
132
+ type ExpectFunction<T, H extends PropertyKey = never> = Exact<T, any> extends true ? unknown : Exact<T, never> extends true ? unknown : [T] extends [(...args: infer Args) => infer R] ? {
133
+ argsType(): ExpectType<Args, H>;
134
+ returnType(): ExpectType<R, H>;
135
+ } : [T] extends [new (...args: infer Args) => infer R] ? {
136
+ argsType(): ExpectType<Args, H>;
137
+ returnType(): ExpectType<R, H>;
138
+ } : unknown;
93
139
  /**
94
140
  * Type-level testing utility that allows checking various relationships between types.
95
141
  * Provides methods to test type equality, extension, properties, and more.
@@ -99,6 +145,8 @@ type ExpectTypeMethods<T, H extends PropertyKey = never> = {
99
145
  *
100
146
  * @example
101
147
  * ```ts
148
+ * import { expect } from '@leawind/lay-sing'
149
+ *
102
150
  * // Test if two types are identical
103
151
  * expect<number>().toBe<number>().success
104
152
  * expect<number>().toBe<string>().fail
@@ -109,7 +157,7 @@ type ExpectTypeMethods<T, H extends PropertyKey = never> = {
109
157
  * expect<{name: string}>().toHaveKey<'name'>().success
110
158
  * ```
111
159
  */
112
- export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMethods<T, H> & {
160
+ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMethods<T, H> & ExpectFunction<T, H> & {
113
161
  T: T;
114
162
  inspect: {
115
163
  [K in keyof T]: T[K];
@@ -121,7 +169,9 @@ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMetho
121
169
  *
122
170
  * @example
123
171
  * ```ts
124
- * expect<3.14>().toExtendNumber // Available and would succeed
172
+ * import { expect } from '@leawind/lay-sing'
173
+ *
174
+ * expect<3.14>().toExtendNumber
125
175
  * ```
126
176
  */
127
177
  toExtendNumber: ExpectType<T, H | 'toExtendNumber' | 'toExtend'>;
@@ -131,7 +181,9 @@ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMetho
131
181
  *
132
182
  * @example
133
183
  * ```ts
134
- * expect<'hello'>().toExtendString // Available and would succeed
184
+ * import { expect } from '@leawind/lay-sing'
185
+ *
186
+ * expect<'hello'>().toExtendString
135
187
  * ```
136
188
  */
137
189
  toExtendString: ExpectType<T, H | 'toExtendString' | 'toExtend'>;
@@ -141,7 +193,9 @@ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMetho
141
193
  *
142
194
  * @example
143
195
  * ```ts
144
- * expect<true>().toExtendBoolean // Available and would succeed
196
+ * import { expect } from '@leawind/lay-sing'
197
+ *
198
+ * expect<true>().toExtendBoolean
145
199
  * ```
146
200
  */
147
201
  toExtendBoolean: ExpectType<T, H | 'toExtendBoolean' | 'toExtend'>;
@@ -150,6 +204,8 @@ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMetho
150
204
  * Alias for {@link ExpectTypeMethods.toBe} where `U = any`
151
205
  *
152
206
  * ```ts
207
+ * import { expect } from '@leawind/lay-sing'
208
+ *
153
209
  * expect<any>().toBeAny
154
210
  * expect<any>().toBe<any>().success
155
211
  * ```
@@ -159,6 +215,8 @@ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMetho
159
215
  * Alias for {@link ExpectTypeMethods.toBe} where `U = never`
160
216
  *
161
217
  * ```ts
218
+ * import { expect } from '@leawind/lay-sing'
219
+ *
162
220
  * expect<never>().toBeNever
163
221
  * expect<never>().toBe<never>().success
164
222
  * ```
@@ -168,6 +226,8 @@ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMetho
168
226
  * Alias for {@link ExpectTypeMethods.toBe} where `U = unknown`
169
227
  *
170
228
  * ```ts
229
+ * import { expect } from '@leawind/lay-sing'
230
+ *
171
231
  * expect<unknown>().toBeUnknown
172
232
  * expect<unknown>().toBe<unknown>().success
173
233
  * ```
@@ -177,6 +237,8 @@ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMetho
177
237
  * Alias for {@link ExpectTypeMethods.toBe} where `U = void`
178
238
  *
179
239
  * ```ts
240
+ * import { expect } from '@leawind/lay-sing'
241
+ *
180
242
  * expect<void>().toBeVoid
181
243
  * expect<void>().toBe<void>().success
182
244
  * ```
@@ -186,6 +248,8 @@ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMetho
186
248
  * Alias for {@link ExpectTypeMethods.toBe} where `U = null`
187
249
  *
188
250
  * ```ts
251
+ * import { expect } from '@leawind/lay-sing'
252
+ *
189
253
  * expect<null>().toBeNull
190
254
  * expect<null>().toBe<null>().success
191
255
  * ```
@@ -195,6 +259,8 @@ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMetho
195
259
  * Alias for {@link ExpectTypeMethods.toBe} where `U = undefined`
196
260
  *
197
261
  * ```ts
262
+ * import { expect } from '@leawind/lay-sing'
263
+ *
198
264
  * expect<undefined>().toBeUndefined
199
265
  * expect<undefined>().toBe<undefined>().success
200
266
  * ```
@@ -204,6 +270,8 @@ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMetho
204
270
  * Alias for {@link ExpectTypeMethods.toBe} where `U = true`
205
271
  *
206
272
  * ```ts
273
+ * import { expect } from '@leawind/lay-sing'
274
+ *
207
275
  * expect<true>().toBeTrue
208
276
  * expect<true>().toBe<true>().success
209
277
  * ```
@@ -213,6 +281,8 @@ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMetho
213
281
  * Alias for {@link ExpectTypeMethods.toBe} where `U = false`
214
282
  *
215
283
  * ```ts
284
+ * import { expect } from '@leawind/lay-sing'
285
+ *
216
286
  * expect<false>().toBeFalse
217
287
  * expect<false>().toBe<false>().success
218
288
  * ```
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect.d.ts","sourceRoot":"","sources":["../../src/main/expect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect.js","sourceRoot":"","sources":["../../src/main/expect.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n Exact,\n Extends,\n If,\n IfTupleIncludes,\n MutuallyAssignable,\n ProperExtend,\n SafePick,\n} from '../utils/index.js'\n\n/**\n * Represents the result of a type assertion based on a boolean condition.\n *\n * - If `true`, the result has a `success` property;\n * - If `false`, the result has a `fail` property;\n * - Otherwise, the result is `never`\n *\n * @template B The boolean condition result (true or false)\n * @template R The type of the result value (default is void)\n */\nexport type TypeAssertionResult<B extends boolean, R = void> = Exact<B, never> extends true ? never\n : [boolean] extends [B] ? never\n : [B] extends [true] ? {\n /**\n * This field exist only when this type assertion succeed\n *\n * If you expect this assertion to fail, use `.fail`\n */\n success: R\n }\n : [B] extends [false] ? {\n /**\n * This field exist only when this type assertion failed\n *\n * If you expect this assertion to success, use `.success`\n */\n fail: R\n }\n : never\n\ntype ExpectTypeMethods<T, H extends PropertyKey = never> = {\n /**\n * Tests if the current type is exactly the same as the provided type U.\n *\n * @template U The type to compare with\n *\n * @example\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<any>().toBe<any>().success\n * expect<never>().toBe<never>().success\n * expect<false>().toBe<true>().fail\n * ```\n */\n toBe<U>(): TypeAssertionResult<Exact<T, U>, ExpectType<T, H>>\n toBe<U>(_: U): TypeAssertionResult<Exact<T, U>, ExpectType<T, H>>\n\n /**\n * Tests if the current type is mutually assignable with the provided type U.\n *\n * It's like:\n *\n * ```ts ignore\n * [T] extends [U] ? [U] extends [T] ? Yes : No : No\n * ```\n *\n * @template U The type to compare with\n *\n * @example\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<{ a: 1; b: 2 }>().toEqual<{ a: 1 } & { b: 2 }>().success\n * expect<1>().toEqual<1 | 2>().fail\n * ```\n */\n toEqual<U>(): TypeAssertionResult<MutuallyAssignable<T, U>, ExpectType<T, H>>\n toEqual<U>(_: U): TypeAssertionResult<MutuallyAssignable<T, U>, ExpectType<T, H>>\n\n /**\n * Tests if the current type T extends the provided type U.\n *\n * @template U The type to check extension against\n *\n * @example\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<3.14>().toExtend<number>().success\n * expect<2>().toExtend<string>().fail\n * expect<'hello'>().toExtend<string>().success\n * ```\n */\n toExtend<U>(): TypeAssertionResult<Extends<T, U>, ExpectType<T, H>>\n toExtend<U>(_: U): TypeAssertionResult<Extends<T, U>, ExpectType<T, H>>\n\n /**\n * Tests if the current type T properly extends the provided type U (extends but is not the same).\n *\n * @template U The type to check proper extension against\n *\n * @example\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<2>().toProperExtend<number>().success\n * expect<'a' | 'b'>().toProperExtend<string>().success\n * expect<number>().toProperExtend<number>().fail\n * ```\n */\n toProperExtend<U>(): TypeAssertionResult<ProperExtend<T, U>, ExpectType<T, H>>\n toProperExtend<U>(_: U): TypeAssertionResult<ProperExtend<T, U>, ExpectType<T, H>>\n\n /**\n * Tests if the current type `T` has a property with key `K`.\n *\n * @template K The property key to check for\n *\n * ### Behavior\n *\n * - For single keys: succeeds if the key exists in `T`\n * - For union types: succeeds only if **all** keys in the union exist in `T`\n *\n * ### Examples\n *\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * type WithProp = { prop: string; another: number; may?: 5 }\n *\n * // Single key checks\n * expect<WithProp>().toHaveKey<'prop'>().success\n * expect<WithProp>().toHaveKey<'missing'>().fail\n *\n * // Union type checks\n * expect<WithProp>().toHaveKey<'prop' | 'another'>().success\n * expect<WithProp>().toHaveKey<'may' | 'unexist'>().fail\n * ```\n */\n toHaveKey<K extends PropertyKey>(): IfTupleIncludes<\n [never, any],\n K,\n never,\n TypeAssertionResult<Extends<K, keyof T>, ExpectType<T, H>>\n >\n toHaveKey<K extends PropertyKey>(_: K): IfTupleIncludes<\n [never, any],\n K,\n never,\n TypeAssertionResult<Extends<K, keyof T>, ExpectType<T, H>>\n >\n}\n\ntype ExpectFunction<T, H extends PropertyKey = never> = Exact<T, any> extends true ? unknown\n : Exact<T, never> extends true ? unknown\n : [T] extends [(...args: infer Args) => infer R] ? {\n argsType(): ExpectType<Args, H>\n returnType(): ExpectType<R, H>\n }\n : [T] extends [new (...args: infer Args) => infer R] ? {\n argsType(): ExpectType<Args, H>\n returnType(): ExpectType<R, H>\n }\n : unknown\n\n/**\n * Type-level testing utility that allows checking various relationships between types.\n * Provides methods to test type equality, extension, properties, and more.\n *\n * @template T The type being tested\n * @template H Hidden property keys that are already used (internal tracking)\n *\n * @example\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * // Test if two types are identical\n * expect<number>().toBe<number>().success\n * expect<number>().toBe<string>().fail\n * // Test if one type extends another\n * expect<2>().toExtend<number>().success\n * expect<2>().toExtend<string>().fail\n * // Test if type has a specific property\n * expect<{name: string}>().toHaveKey<'name'>().success\n * ```\n */\nexport type ExpectType<T, H extends PropertyKey = never> = Omit<\n (\n & ExpectTypeMethods<T, H>\n & ExpectFunction<T, H>\n & {\n T: T\n inspect: { [K in keyof T]: T[K] }\n }\n & SafePick<\n {\n /**\n * Tests if the current type extends the Number primitive type.\n * Available only if the current type extends number.\n *\n * @example\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<3.14>().toExtendNumber\n * ```\n */\n toExtendNumber: ExpectType<T, H | 'toExtendNumber' | 'toExtend'>\n\n /**\n * Tests if the current type extends the String primitive type.\n * Available only if the current type extends string.\n *\n * @example\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<'hello'>().toExtendString\n * ```\n */\n toExtendString: ExpectType<T, H | 'toExtendString' | 'toExtend'>\n\n /**\n * Tests if the current type extends the Boolean primitive type.\n * Available only if the current type extends boolean.\n *\n * @example\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<true>().toExtendBoolean\n * ```\n */\n toExtendBoolean: ExpectType<T, H | 'toExtendBoolean' | 'toExtend'>\n },\n | If<Extends<T, number>, 'toExtendNumber'>\n | If<Extends<T, string>, 'toExtendString'>\n | If<Extends<T, boolean>, 'toExtendBoolean'>\n >\n & SafePick<\n {\n /**\n * Alias for {@link ExpectTypeMethods.toBe} where `U = any`\n *\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<any>().toBeAny\n * expect<any>().toBe<any>().success\n * ```\n */\n toBeAny: ExpectType<T, H | 'toBeAny' | 'toBe'>\n\n /**\n * Alias for {@link ExpectTypeMethods.toBe} where `U = never`\n *\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<never>().toBeNever\n * expect<never>().toBe<never>().success\n * ```\n */\n toBeNever: ExpectType<T, H | 'toBeNever' | 'toBe'>\n\n /**\n * Alias for {@link ExpectTypeMethods.toBe} where `U = unknown`\n *\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<unknown>().toBeUnknown\n * expect<unknown>().toBe<unknown>().success\n * ```\n */\n toBeUnknown: ExpectType<T, H | 'toBeUnknown' | 'toBe'>\n\n /**\n * Alias for {@link ExpectTypeMethods.toBe} where `U = void`\n *\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<void>().toBeVoid\n * expect<void>().toBe<void>().success\n * ```\n */\n toBeVoid: ExpectType<T, H | 'toBeVoid' | 'toBe'>\n\n /**\n * Alias for {@link ExpectTypeMethods.toBe} where `U = null`\n *\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<null>().toBeNull\n * expect<null>().toBe<null>().success\n * ```\n */\n toBeNull: ExpectType<T, H | 'toBeNull' | 'toBe'>\n\n /**\n * Alias for {@link ExpectTypeMethods.toBe} where `U = undefined`\n *\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<undefined>().toBeUndefined\n * expect<undefined>().toBe<undefined>().success\n * ```\n */\n toBeUndefined: ExpectType<T, H | 'toBeUndefined' | 'toBe'>\n\n /**\n * Alias for {@link ExpectTypeMethods.toBe} where `U = true`\n *\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<true>().toBeTrue\n * expect<true>().toBe<true>().success\n * ```\n */\n toBeTrue: ExpectType<T, H | 'toBeTrue' | 'toBe' | 'toExtendBoolean'>\n\n /**\n * Alias for {@link ExpectTypeMethods.toBe} where `U = false`\n *\n * ```ts\n * import { expect } from '@leawind/lay-sing'\n *\n * expect<false>().toBeFalse\n * expect<false>().toBe<false>().success\n * ```\n */\n toBeFalse: ExpectType<T, H | 'toBeFalse' | 'toBe' | 'toExtendBoolean'>\n },\n | If<Exact<T, any>, 'toBeAny'>\n | If<Exact<T, never>, 'toBeNever'>\n | If<Exact<T, unknown>, 'toBeUnknown'>\n | If<Exact<T, void>, 'toBeVoid'>\n | If<Exact<T, null>, 'toBeNull'>\n | If<Exact<T, undefined>, 'toBeUndefined'>\n | If<Exact<T, true>, 'toBeTrue'>\n | If<Exact<T, false>, 'toBeFalse'>\n >\n ),\n H\n>\n"]}
@@ -1,12 +1,30 @@
1
- export * from './async.js';
2
- export * from './boolean.js';
3
- export * from './control.js';
4
- export * from './doc.js';
5
- export * from './function.js';
6
- export * from './json.js';
7
- export * from './key.js';
8
- export * from './object.js';
9
- export * from './tuple.js';
10
- export * from './type/index.js';
11
- export * from './typed-array.js';
1
+ /**
2
+ * [Full API documentation is available on JSR](https://jsr.io/@leawind/lay-sing/doc)
3
+ *
4
+ * @module
5
+ */
6
+ import type { ExpectType } from './expect.js';
7
+ export type { ExpectType } from './expect.js';
8
+ export { NOOP } from './noop.js';
9
+ /**
10
+ * Creates an instance of ExpectType to perform type-level assertions on the given type.
11
+ * This function enables testing various type relationships at compile time.
12
+ * NOTE: This function does nothing at runtime and is purely for type-level testing.
13
+ *
14
+ * @template T The type to be tested
15
+ *
16
+ * @returns An ExpectType instance with methods to test type relationships
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * // Test exact type equality
21
+ * expect<number>().toBe<number>().success
22
+ * expect<number>().toBe<string>().fail
23
+ * // Test if one type extends another
24
+ * expect<3.14>().toExtend<number>().success
25
+ * expect<2>().toExtend<string>().fail
26
+ * ```
27
+ */
28
+ export declare function expect<T>(): ExpectType<T>;
29
+ export declare function expect<T>(_: T): ExpectType<T>;
12
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/main/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/main/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAG7C,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,MAAM,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CAAA;AAC1C,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA"}
package/esm/main/index.js CHANGED
@@ -1,14 +1,11 @@
1
- // Index start >>>>>>>>>>>>>>>>
2
- export * from './async.js';
3
- export * from './boolean.js';
4
- export * from './control.js';
5
- export * from './doc.js';
6
- export * from './function.js';
7
- export * from './json.js';
8
- export * from './key.js';
9
- export * from './object.js';
10
- export * from './tuple.js';
11
- export * from './type/index.js';
12
- export * from './typed-array.js';
13
- // <<<<<<<<<<<<<<<< Index end
1
+ /**
2
+ * [Full API documentation is available on JSR](https://jsr.io/@leawind/lay-sing/doc)
3
+ *
4
+ * @module
5
+ */
6
+ import { NOOP } from './noop.js';
7
+ export { NOOP } from './noop.js';
8
+ export function expect() {
9
+ return NOOP;
10
+ }
14
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/main/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,kBAAkB,CAAA;AAChC,+BAA+B","sourcesContent":["// Index start >>>>>>>>>>>>>>>>\nexport * from './async.js'\nexport * from './boolean.js'\nexport * from './control.js'\nexport * from './doc.js'\nexport * from './function.js'\nexport * from './json.js'\nexport * from './key.js'\nexport * from './object.js'\nexport * from './tuple.js'\nexport * from './type/index.js'\nexport * from './typed-array.js'\n// <<<<<<<<<<<<<<<< Index end\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/main/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAGhC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAuBhC,MAAM,UAAU,MAAM;IACpB,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["/**\n * [Full API documentation is available on JSR](https://jsr.io/@leawind/lay-sing/doc)\n *\n * @module\n */\n\nimport type { ExpectType } from './expect.js'\nimport { NOOP } from './noop.js'\n\nexport type { ExpectType } from './expect.js'\nexport { NOOP } from './noop.js'\n\n/**\n * Creates an instance of ExpectType to perform type-level assertions on the given type.\n * This function enables testing various type relationships at compile time.\n * NOTE: This function does nothing at runtime and is purely for type-level testing.\n *\n * @template T The type to be tested\n *\n * @returns An ExpectType instance with methods to test type relationships\n *\n * @example\n * ```ts\n * // Test exact type equality\n * expect<number>().toBe<number>().success\n * expect<number>().toBe<string>().fail\n * // Test if one type extends another\n * expect<3.14>().toExtend<number>().success\n * expect<2>().toExtend<string>().fail\n * ```\n */\nexport function expect<T>(): ExpectType<T>\nexport function expect<T>(_: T): ExpectType<T>\nexport function expect<T>(): ExpectType<T> {\n return NOOP\n}\n"]}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * A universal no-op placeholder implemented via `Proxy`.
3
+ *
4
+ * `NOOP` can be accessed, called, or chained indefinitely without throwing.
5
+ * Every operation returns itself, making it safe to use as a dummy fallback
6
+ * for APIs, optional hooks, or unimplemented interfaces.
7
+ *
8
+ * ### Special behaviors
9
+ *
10
+ * - Callable: invoking `NOOP()` returns `NOOP`
11
+ * - Property access: `NOOP.anything` returns `NOOP`
12
+ * - Promise-safe: `NOOP.then` is `undefined`, so it is not treated as a Promise
13
+ * - Primitive coercion (`toString`, `valueOf`, `Symbol.toPrimitive`) yields
14
+ * a stable string representation: `"[NOOP]"`
15
+ *
16
+ * This is useful in scenarios where a value is required syntactically but
17
+ * should perform no action and never fail at runtime.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * NOOP.foo.bar().baz.qux; // safe, returns NOOP
22
+ * String(NOOP); // "[NOOP]"
23
+ * await NOOP; // does not await (not thenable)
24
+ * ```
25
+ */
26
+ export declare const NOOP: any;
27
+ //# sourceMappingURL=noop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noop.d.ts","sourceRoot":"","sources":["../../src/main/noop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,IAAI,EAAE,GA0BlB,CAAA"}
@@ -23,7 +23,6 @@
23
23
  * await NOOP; // does not await (not thenable)
24
24
  * ```
25
25
  */
26
- // deno-lint-ignore no-explicit-any
27
26
  export const NOOP = new Proxy(function () {
28
27
  return NOOP;
29
28
  }, {
@@ -48,10 +47,4 @@ export const NOOP = new Proxy(function () {
48
47
  has: () => true,
49
48
  ownKeys: () => ['prototype'],
50
49
  });
51
- export function compare() {
52
- return NOOP;
53
- }
54
- export function expect() {
55
- return NOOP;
56
- }
57
- //# sourceMappingURL=index.js.map
50
+ //# sourceMappingURL=noop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noop.js","sourceRoot":"","sources":["../../src/main/noop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,IAAI,GAAQ,IAAI,KAAK,CAChC;IACE,OAAO,IAAI,CAAA;AACb,CAAC,EACD;IACE,GAAG,CAAC,CAAC,EAAE,IAAI;QACT,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,MAAM;gBACT,OAAO,SAAS,CAAA;YAClB,KAAK,SAAS,CAAC;YACf,KAAK,UAAU,CAAC;YAChB,KAAK,MAAM,CAAC,WAAW;gBACrB,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAA;YACvB;gBACE,OAAO,IAAI,CAAA;QACf,CAAC;IACH,CAAC;IACD,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI;IACf,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/B,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,IAAI;KACZ,CAAC;IACF,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI;IAC1B,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI;IACf,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC;CAC7B,CACF,CAAA","sourcesContent":["/**\n * A universal no-op placeholder implemented via `Proxy`.\n *\n * `NOOP` can be accessed, called, or chained indefinitely without throwing.\n * Every operation returns itself, making it safe to use as a dummy fallback\n * for APIs, optional hooks, or unimplemented interfaces.\n *\n * ### Special behaviors\n *\n * - Callable: invoking `NOOP()` returns `NOOP`\n * - Property access: `NOOP.anything` returns `NOOP`\n * - Promise-safe: `NOOP.then` is `undefined`, so it is not treated as a Promise\n * - Primitive coercion (`toString`, `valueOf`, `Symbol.toPrimitive`) yields\n * a stable string representation: `\"[NOOP]\"`\n *\n * This is useful in scenarios where a value is required syntactically but\n * should perform no action and never fail at runtime.\n *\n * @example\n * ```ts\n * NOOP.foo.bar().baz.qux; // safe, returns NOOP\n * String(NOOP); // \"[NOOP]\"\n * await NOOP; // does not await (not thenable)\n * ```\n */\nexport const NOOP: any = new Proxy(\n function () {\n return NOOP\n },\n {\n get(_, prop) {\n switch (prop) {\n case 'then':\n return undefined\n case 'valueOf':\n case 'toString':\n case Symbol.toPrimitive:\n return () => '[NOOP]'\n default:\n return NOOP\n }\n },\n set: () => true,\n getOwnPropertyDescriptor: () => ({\n configurable: true,\n value: NOOP,\n }),\n getPrototypeOf: () => null,\n has: () => true,\n ownKeys: () => ['prototype'],\n },\n)\n"]}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Checks whether two types are mutually assignable.
3
+ *
4
+ * This is equivalent to checking that:
5
+ * - `A` extends `B`
6
+ * - `B` extends `A`
7
+ *
8
+ * In other words, the two types describe the same set of values,
9
+ * even if they are written differently.
10
+ *
11
+ * @template A - The first type to check
12
+ * @template B - The second type to check
13
+ * @template Yes - The result if types are mutually assignable (defaults to `true`)
14
+ * @template No - The result if types are not mutually assignable (defaults to `false`)
15
+ *
16
+ * ### Result
17
+ *
18
+ * - `Yes`: `A` and `B` are mutually assignable
19
+ * - `No`: Otherwise
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * type T1 = MutuallyAssignable<number, number> // true
24
+ * type T2 = MutuallyAssignable<1 | 2, 2 | 1> // true
25
+ * type F1 = MutuallyAssignable<string, number> // false
26
+ * type F2 = MutuallyAssignable<1, number> // false
27
+ * ```
28
+ */
29
+ export type MutuallyAssignable<A, B, Yes = true, No = false> = [A] extends [B] ? [B] extends [A] ? Yes : No : No;
30
+ //# sourceMappingURL=assignable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assignable.d.ts","sourceRoot":"","sources":["../../../src/utils/compare/assignable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,MAAM,kBAAkB,CAC5B,CAAC,EACD,CAAC,EACD,GAAG,GAAG,IAAI,EACV,EAAE,GAAG,KAAK,IACR,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=assignable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assignable.js","sourceRoot":"","sources":["../../../src/utils/compare/assignable.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Checks whether two types are mutually assignable.\n *\n * This is equivalent to checking that:\n * - `A` extends `B`\n * - `B` extends `A`\n *\n * In other words, the two types describe the same set of values,\n * even if they are written differently.\n *\n * @template A - The first type to check\n * @template B - The second type to check\n * @template Yes - The result if types are mutually assignable (defaults to `true`)\n * @template No - The result if types are not mutually assignable (defaults to `false`)\n *\n * ### Result\n *\n * - `Yes`: `A` and `B` are mutually assignable\n * - `No`: Otherwise\n *\n * @example\n * ```ts\n * type T1 = MutuallyAssignable<number, number> // true\n * type T2 = MutuallyAssignable<1 | 2, 2 | 1> // true\n * type F1 = MutuallyAssignable<string, number> // false\n * type F2 = MutuallyAssignable<1, number> // false\n * ```\n */\nexport type MutuallyAssignable<\n A,\n B,\n Yes = true,\n No = false,\n> = [A] extends [B] ? [B] extends [A] ? Yes : No : No\n"]}