lay-sing 0.1.2 → 0.2.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 (103) hide show
  1. package/README.md +40 -67
  2. package/esm/main/boolean.d.ts +1 -2
  3. package/esm/main/boolean.d.ts.map +1 -1
  4. package/esm/main/boolean.js.map +1 -1
  5. package/esm/main/control.d.ts +15 -20
  6. package/esm/main/control.d.ts.map +1 -1
  7. package/esm/main/control.js.map +1 -1
  8. package/esm/main/function.d.ts +2 -4
  9. package/esm/main/function.d.ts.map +1 -1
  10. package/esm/main/function.js.map +1 -1
  11. package/esm/main/index.d.ts +1 -1
  12. package/esm/main/index.d.ts.map +1 -1
  13. package/esm/main/index.js +3 -1
  14. package/esm/main/index.js.map +1 -1
  15. package/esm/main/key.d.ts +53 -17
  16. package/esm/main/key.d.ts.map +1 -1
  17. package/esm/main/key.js.map +1 -1
  18. package/esm/main/object.d.ts +45 -31
  19. package/esm/main/object.d.ts.map +1 -1
  20. package/esm/main/object.js.map +1 -1
  21. package/esm/main/tuple.d.ts +40 -0
  22. package/esm/main/tuple.d.ts.map +1 -0
  23. package/esm/main/tuple.js +2 -0
  24. package/esm/main/tuple.js.map +1 -0
  25. package/esm/main/type/compare.d.ts +9 -9
  26. package/esm/main/type/compare.d.ts.map +1 -1
  27. package/esm/main/type/compare.js.map +1 -1
  28. package/esm/main/type/index.d.ts.map +1 -1
  29. package/esm/main/type/index.js +2 -0
  30. package/esm/main/type/index.js.map +1 -1
  31. package/esm/main/type/set.d.ts +4 -6
  32. package/esm/main/type/set.d.ts.map +1 -1
  33. package/esm/main/type/set.js.map +1 -1
  34. package/esm/test-utils/compare.d.ts +69 -0
  35. package/esm/test-utils/compare.d.ts.map +1 -0
  36. package/esm/test-utils/compare.js +2 -0
  37. package/esm/test-utils/compare.js.map +1 -0
  38. package/esm/test-utils/expect.d.ts +223 -0
  39. package/esm/test-utils/expect.d.ts.map +1 -0
  40. package/esm/test-utils/expect.js +2 -0
  41. package/esm/test-utils/expect.js.map +1 -0
  42. package/esm/test-utils/index.d.ts +72 -0
  43. package/esm/test-utils/index.d.ts.map +1 -0
  44. package/esm/{test-utils.js → test-utils/index.js} +5 -5
  45. package/esm/test-utils/index.js.map +1 -0
  46. package/package.json +3 -3
  47. package/script/main/boolean.d.ts +1 -2
  48. package/script/main/boolean.d.ts.map +1 -1
  49. package/script/main/boolean.js.map +1 -1
  50. package/script/main/control.d.ts +15 -20
  51. package/script/main/control.d.ts.map +1 -1
  52. package/script/main/control.js.map +1 -1
  53. package/script/main/function.d.ts +2 -4
  54. package/script/main/function.d.ts.map +1 -1
  55. package/script/main/function.js.map +1 -1
  56. package/script/main/index.d.ts +1 -1
  57. package/script/main/index.d.ts.map +1 -1
  58. package/script/main/index.js +3 -1
  59. package/script/main/index.js.map +1 -1
  60. package/script/main/key.d.ts +53 -17
  61. package/script/main/key.d.ts.map +1 -1
  62. package/script/main/key.js.map +1 -1
  63. package/script/main/object.d.ts +45 -31
  64. package/script/main/object.d.ts.map +1 -1
  65. package/script/main/object.js.map +1 -1
  66. package/script/main/tuple.d.ts +40 -0
  67. package/script/main/tuple.d.ts.map +1 -0
  68. package/script/main/{array.js → tuple.js} +1 -1
  69. package/script/main/tuple.js.map +1 -0
  70. package/script/main/type/compare.d.ts +9 -9
  71. package/script/main/type/compare.d.ts.map +1 -1
  72. package/script/main/type/compare.js.map +1 -1
  73. package/script/main/type/index.d.ts.map +1 -1
  74. package/script/main/type/index.js +2 -0
  75. package/script/main/type/index.js.map +1 -1
  76. package/script/main/type/set.d.ts +4 -6
  77. package/script/main/type/set.d.ts.map +1 -1
  78. package/script/main/type/set.js.map +1 -1
  79. package/script/test-utils/compare.d.ts +69 -0
  80. package/script/test-utils/compare.d.ts.map +1 -0
  81. package/script/test-utils/compare.js +3 -0
  82. package/script/test-utils/compare.js.map +1 -0
  83. package/script/test-utils/expect.d.ts +223 -0
  84. package/script/test-utils/expect.d.ts.map +1 -0
  85. package/script/test-utils/expect.js +3 -0
  86. package/script/test-utils/expect.js.map +1 -0
  87. package/script/test-utils/index.d.ts +72 -0
  88. package/script/test-utils/index.d.ts.map +1 -0
  89. package/script/{test-utils.js → test-utils/index.js} +6 -6
  90. package/script/test-utils/index.js.map +1 -0
  91. package/esm/main/array.d.ts +0 -48
  92. package/esm/main/array.d.ts.map +0 -1
  93. package/esm/main/array.js +0 -2
  94. package/esm/main/array.js.map +0 -1
  95. package/esm/test-utils.d.ts +0 -348
  96. package/esm/test-utils.d.ts.map +0 -1
  97. package/esm/test-utils.js.map +0 -1
  98. package/script/main/array.d.ts +0 -48
  99. package/script/main/array.d.ts.map +0 -1
  100. package/script/main/array.js.map +0 -1
  101. package/script/test-utils.d.ts +0 -348
  102. package/script/test-utils.d.ts.map +0 -1
  103. package/script/test-utils.js.map +0 -1
@@ -0,0 +1,223 @@
1
+ import type { Exact, Extends, If, IfTupleIncludes, ProperExtend, SafePick } from '../main/index.js';
2
+ /**
3
+ * Represents the result of a type assertion based on a boolean condition.
4
+ *
5
+ * - If `true`, the result has a `success` property;
6
+ * - If `false`, the result has a `fail` property;
7
+ * - Otherwise, the result is `never`
8
+ *
9
+ * @template B The boolean condition result (true or false)
10
+ * @template R The type of the result value (default is void)
11
+ */
12
+ export type TypeAssertionResult<B extends boolean, R = void> = Exact<B, never> extends true ? never : [boolean] extends [B] ? never : [B] extends [true] ? {
13
+ /**
14
+ * This field exist only when this type assertion succeed
15
+ *
16
+ * If you expect this assertion to fail, use `.fail`
17
+ */
18
+ success: R;
19
+ } : [B] extends [false] ? {
20
+ /**
21
+ * This field exist only when this type assertion failed
22
+ *
23
+ * If you expect this assertion to success, use `.success`
24
+ */
25
+ fail: R;
26
+ } : never;
27
+ type ExpectTypeMethods<T, H extends PropertyKey = never> = {
28
+ /**
29
+ * Tests if the current type is exactly the same as the provided type U.
30
+ *
31
+ * @template U The type to compare with
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * expect<any>().toBe<any>().success
36
+ * expect<never>().toBe<never>().success
37
+ * expect<false>().toBe<true>().fail
38
+ * ```
39
+ */
40
+ toBe<U>(): TypeAssertionResult<Exact<T, U>>;
41
+ /**
42
+ * Tests if the current type T extends the provided type U.
43
+ *
44
+ * @template U The type to check extension against
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * expect<3.14>().toExtend<number>().success
49
+ * expect<2>().toExtend<string>().fail
50
+ * expect<'hello'>().toExtend<string>().success
51
+ * ```
52
+ */
53
+ toExtend<U>(): TypeAssertionResult<Extends<T, U>>;
54
+ /**
55
+ * Tests if the current type T properly extends the provided type U (extends but is not the same).
56
+ *
57
+ * @template U The type to check proper extension against
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * expect<2>().toProperExtend<number>().success
62
+ * expect<'a' | 'b'>().toProperExtend<string>().success
63
+ * expect<number>().toProperExtend<number>().fail
64
+ * ```
65
+ */
66
+ toProperExtend<U>(): TypeAssertionResult<ProperExtend<T, U>>;
67
+ /**
68
+ * Tests if the current type `T` has a property with key `K`.
69
+ *
70
+ * @template K The property key to check for
71
+ *
72
+ * ### Behavior
73
+ *
74
+ * - For single keys: succeeds if the key exists in `T`
75
+ * - For union types: succeeds only if **all** keys in the union exist in `T`
76
+ *
77
+ * ### Examples
78
+ *
79
+ * ```ts
80
+ * type WithProp = { prop: string; another: number; may?: 5 }
81
+ *
82
+ * // Single key checks
83
+ * expect<WithProp>().toHaveKey<'prop'>().success
84
+ * expect<WithProp>().toHaveKey<'missing'>().fail
85
+ *
86
+ * // Union type checks
87
+ * expect<WithProp>().toHaveKey<'prop' | 'another'>().success
88
+ * expect<WithProp>().toHaveKey<'may' | 'unexist'>().fail
89
+ * ```
90
+ */
91
+ toHaveKey<K extends PropertyKey>(): IfTupleIncludes<[never, any], K, never, TypeAssertionResult<Extends<K, keyof T>>>;
92
+ };
93
+ /**
94
+ * Type-level testing utility that allows checking various relationships between types.
95
+ * Provides methods to test type equality, extension, properties, and more.
96
+ *
97
+ * @template T The type being tested
98
+ * @template H Hidden property keys that are already used (internal tracking)
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * // Test if two types are identical
103
+ * expect<number>().toBe<number>().success
104
+ * expect<number>().toBe<string>().fail
105
+ * // Test if one type extends another
106
+ * expect<2>().toExtend<number>().success
107
+ * expect<2>().toExtend<string>().fail
108
+ * // Test if type has a specific property
109
+ * expect<{name: string}>().toHaveKey<'name'>().success
110
+ * ```
111
+ */
112
+ export type ExpectType<T, H extends PropertyKey = never> = Omit<(ExpectTypeMethods<T, H> & {
113
+ T: T;
114
+ inspect: {
115
+ [K in keyof T]: T[K];
116
+ };
117
+ } & SafePick<{
118
+ /**
119
+ * Tests if the current type extends the Number primitive type.
120
+ * Available only if the current type extends number.
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * expect<3.14>().toExtendNumber // Available and would succeed
125
+ * ```
126
+ */
127
+ toExtendNumber: ExpectType<T, H | 'toExtendNumber' | 'toExtend'>;
128
+ /**
129
+ * Tests if the current type extends the String primitive type.
130
+ * Available only if the current type extends string.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * expect<'hello'>().toExtendString // Available and would succeed
135
+ * ```
136
+ */
137
+ toExtendString: ExpectType<T, H | 'toExtendString' | 'toExtend'>;
138
+ /**
139
+ * Tests if the current type extends the Boolean primitive type.
140
+ * Available only if the current type extends boolean.
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * expect<true>().toExtendBoolean // Available and would succeed
145
+ * ```
146
+ */
147
+ toExtendBoolean: ExpectType<T, H | 'toExtendBoolean' | 'toExtend'>;
148
+ }, If<Extends<T, number>, 'toExtendNumber'> | If<Extends<T, string>, 'toExtendString'> | If<Extends<T, boolean>, 'toExtendBoolean'>> & SafePick<{
149
+ /**
150
+ * Alias for {@link ExpectTypeMethods.toBe} where `U = any`
151
+ *
152
+ * ```ts
153
+ * expect<any>().toBeAny
154
+ * expect<any>().toBe<any>().success
155
+ * ```
156
+ */
157
+ toBeAny: ExpectType<T, H | 'toBeAny' | 'toBe'>;
158
+ /**
159
+ * Alias for {@link ExpectTypeMethods.toBe} where `U = never`
160
+ *
161
+ * ```ts
162
+ * expect<never>().toBeNever
163
+ * expect<never>().toBe<never>().success
164
+ * ```
165
+ */
166
+ toBeNever: ExpectType<T, H | 'toBeNever' | 'toBe'>;
167
+ /**
168
+ * Alias for {@link ExpectTypeMethods.toBe} where `U = unknown`
169
+ *
170
+ * ```ts
171
+ * expect<unknown>().toBeUnknown
172
+ * expect<unknown>().toBe<unknown>().success
173
+ * ```
174
+ */
175
+ toBeUnknown: ExpectType<T, H | 'toBeUnknown' | 'toBe'>;
176
+ /**
177
+ * Alias for {@link ExpectTypeMethods.toBe} where `U = void`
178
+ *
179
+ * ```ts
180
+ * expect<void>().toBeVoid
181
+ * expect<void>().toBe<void>().success
182
+ * ```
183
+ */
184
+ toBeVoid: ExpectType<T, H | 'toBeVoid' | 'toBe'>;
185
+ /**
186
+ * Alias for {@link ExpectTypeMethods.toBe} where `U = null`
187
+ *
188
+ * ```ts
189
+ * expect<null>().toBeNull
190
+ * expect<null>().toBe<null>().success
191
+ * ```
192
+ */
193
+ toBeNull: ExpectType<T, H | 'toBeNull' | 'toBe'>;
194
+ /**
195
+ * Alias for {@link ExpectTypeMethods.toBe} where `U = undefined`
196
+ *
197
+ * ```ts
198
+ * expect<undefined>().toBeUndefined
199
+ * expect<undefined>().toBe<undefined>().success
200
+ * ```
201
+ */
202
+ toBeUndefined: ExpectType<T, H | 'toBeUndefined' | 'toBe'>;
203
+ /**
204
+ * Alias for {@link ExpectTypeMethods.toBe} where `U = true`
205
+ *
206
+ * ```ts
207
+ * expect<true>().toBeTrue
208
+ * expect<true>().toBe<true>().success
209
+ * ```
210
+ */
211
+ toBeTrue: ExpectType<T, H | 'toBeTrue' | 'toBe' | 'toExtendBoolean'>;
212
+ /**
213
+ * Alias for {@link ExpectTypeMethods.toBe} where `U = false`
214
+ *
215
+ * ```ts
216
+ * expect<false>().toBeFalse
217
+ * expect<false>().toBe<false>().success
218
+ * ```
219
+ */
220
+ toBeFalse: ExpectType<T, H | 'toBeFalse' | 'toBe' | 'toExtendBoolean'>;
221
+ }, If<Exact<T, any>, 'toBeAny'> | If<Exact<T, never>, 'toBeNever'> | If<Exact<T, unknown>, 'toBeUnknown'> | If<Exact<T, void>, 'toBeVoid'> | If<Exact<T, null>, 'toBeNull'> | If<Exact<T, undefined>, 'toBeUndefined'> | If<Exact<T, true>, 'toBeTrue'> | If<Exact<T, false>, 'toBeFalse'>>), H>;
222
+ export {};
223
+ //# sourceMappingURL=expect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect.d.ts","sourceRoot":"","sources":["../../src/test-utils/expect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=expect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect.js","sourceRoot":"","sources":["../../src/test-utils/expect.ts"],"names":[],"mappings":"","sourcesContent":["// deno-lint-ignore-file no-explicit-any\nimport type { Exact, Extends, If, IfTupleIncludes, ProperExtend, SafePick } from '../main/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 * 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>>\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 * 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>>\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 * 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>>\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 * 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<[never, any], K, never, TypeAssertionResult<Extends<K, keyof T>>>\n}\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 * // 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 & {\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 * expect<3.14>().toExtendNumber // Available and would succeed\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 * expect<'hello'>().toExtendString // Available and would succeed\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 * expect<true>().toExtendBoolean // Available and would succeed\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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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"]}
@@ -0,0 +1,72 @@
1
+ import type { CompareTypes } from './compare.js';
2
+ import type { ExpectType } from './expect.js';
3
+ export type { CompareTypes } from './compare.js';
4
+ export type { ExpectType } from './expect.js';
5
+ /**
6
+ * A universal no-op placeholder implemented via `Proxy`.
7
+ *
8
+ * `NOOP` can be accessed, called, or chained indefinitely without throwing.
9
+ * Every operation returns itself, making it safe to use as a dummy fallback
10
+ * for APIs, optional hooks, or unimplemented interfaces.
11
+ *
12
+ * ### Special behaviors
13
+ *
14
+ * - Callable: invoking `NOOP()` returns `NOOP`
15
+ * - Property access: `NOOP.anything` returns `NOOP`
16
+ * - Promise-safe: `NOOP.then` is `undefined`, so it is not treated as a Promise
17
+ * - Primitive coercion (`toString`, `valueOf`, `Symbol.toPrimitive`) yields
18
+ * a stable string representation: `"[NOOP]"`
19
+ *
20
+ * This is useful in scenarios where a value is required syntactically but
21
+ * should perform no action and never fail at runtime.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * NOOP.foo.bar().baz.qux; // safe, returns NOOP
26
+ * String(NOOP); // "[NOOP]"
27
+ * await NOOP; // does not await (not thenable)
28
+ * ```
29
+ */
30
+ export declare const NOOP: any;
31
+ /**
32
+ * Creates an instance of CompareTypes to perform type-level comparisons between two types.
33
+ * This function enables testing various relationships between types at compile time.
34
+ * NOTE: This function does nothing at runtime and is purely for type-level testing.
35
+ *
36
+ * @template T First type to compare
37
+ * @template U Second type to compare
38
+ *
39
+ * @returns A CompareTypes instance with methods to test relationships between T and U
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * // Compare two identical types
44
+ * compare<number, number>().same // Results in an available property
45
+ * // Compare two different but overlapping types
46
+ * compare<4, number>().overlap.different // Results in available properties
47
+ * ```
48
+ */
49
+ export declare function compare<T, U>(): CompareTypes<T, U>;
50
+ export declare function compare<T, U>(t: T, u: U): CompareTypes<T, U>;
51
+ /**
52
+ * Creates an instance of ExpectType to perform type-level assertions on the given type.
53
+ * This function enables testing various type relationships at compile time.
54
+ * NOTE: This function does nothing at runtime and is purely for type-level testing.
55
+ *
56
+ * @template T The type to be tested
57
+ *
58
+ * @returns An ExpectType instance with methods to test type relationships
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * // Test exact type equality
63
+ * expect<number>().toBe<number>().success
64
+ * expect<number>().toBe<string>().fail
65
+ * // Test if one type extends another
66
+ * expect<3.14>().toExtend<number>().success
67
+ * expect<2>().toExtend<string>().fail
68
+ * ```
69
+ */
70
+ export declare function expect<T>(): ExpectType<T>;
71
+ export declare function expect<T>(_: T): ExpectType<T>;
72
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,eAAO,MAAM,IAAI,EAAE,GA0BlB,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AACnD,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AAK7D;;;;;;;;;;;;;;;;;;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"}
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NOOP = void 0;
4
- exports.expect = expect;
5
4
  exports.compare = compare;
5
+ exports.expect = expect;
6
6
  /**
7
7
  * A universal no-op placeholder implemented via `Proxy`.
8
8
  *
@@ -21,14 +21,14 @@ exports.compare = compare;
21
21
  * This is useful in scenarios where a value is required syntactically but
22
22
  * should perform no action and never fail at runtime.
23
23
  *
24
- * ### Examples
25
- *
24
+ * @example
26
25
  * ```ts
27
26
  * NOOP.foo.bar().baz.qux; // safe, returns NOOP
28
27
  * String(NOOP); // "[NOOP]"
29
28
  * await NOOP; // does not await (not thenable)
30
29
  * ```
31
30
  */
31
+ // deno-lint-ignore no-explicit-any
32
32
  exports.NOOP = new Proxy(function () {
33
33
  return exports.NOOP;
34
34
  }, {
@@ -53,10 +53,10 @@ exports.NOOP = new Proxy(function () {
53
53
  has: () => true,
54
54
  ownKeys: () => ['prototype'],
55
55
  });
56
- function expect() {
56
+ function compare() {
57
57
  return exports.NOOP;
58
58
  }
59
- function compare() {
59
+ function expect() {
60
60
  return exports.NOOP;
61
61
  }
62
- //# sourceMappingURL=test-utils.js.map
62
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test-utils/index.ts"],"names":[],"mappings":";;;AAgFA,0BAEC;AAuBD,wBAEC;AArGD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,mCAAmC;AACtB,QAAA,IAAI,GAAQ,IAAI,KAAK,CAChC;IACE,OAAO,YAAI,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,YAAI,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,YAAI;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;AAsBD,SAAgB,OAAO;IACrB,OAAO,YAAI,CAAA;AACb,CAAC;AAuBD,SAAgB,MAAM;IACpB,OAAO,YAAI,CAAA;AACb,CAAC","sourcesContent":["import type { CompareTypes } from './compare.js'\nimport type { ExpectType } from './expect.js'\n\nexport type { CompareTypes } from './compare.js'\nexport type { ExpectType } from './expect.js'\n\n/**\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 */\n// deno-lint-ignore no-explicit-any\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\n/**\n * Creates an instance of CompareTypes to perform type-level comparisons between two types.\n * This function enables testing various relationships between types at compile time.\n * NOTE: This function does nothing at runtime and is purely for type-level testing.\n *\n * @template T First type to compare\n * @template U Second type to compare\n *\n * @returns A CompareTypes instance with methods to test relationships between T and U\n *\n * @example\n * ```ts\n * // Compare two identical types\n * compare<number, number>().same // Results in an available property\n * // Compare two different but overlapping types\n * compare<4, number>().overlap.different // Results in available properties\n * ```\n */\nexport function compare<T, U>(): CompareTypes<T, U>\nexport function compare<T, U>(t: T, u: U): CompareTypes<T, U>\nexport function compare<T, U>(): CompareTypes<T, U> {\n return NOOP\n}\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"]}
@@ -1,48 +0,0 @@
1
- import type { Same } from './type/compare.js';
2
- /**
3
- * Represents a readonly array of type T
4
- */
5
- export type ReadonlyArray<T = unknown> = readonly T[];
6
- /**
7
- * Concatenates two tuples into a single tuple type
8
- *
9
- * ### Examples
10
- *
11
- * ```ts
12
- * type Result = ConcatTuple<[1, 2], [3, 4]> // [1, 2, 3, 4]
13
- * ```
14
- */
15
- export type ConcatTuple<Left extends readonly unknown[], Right extends readonly unknown[]> = Left extends readonly unknown[] ? (Right extends readonly unknown[] ? [...Left, ...Right] : never) : never;
16
- /**
17
- * Checks whether a tuple includes a specific element type
18
- *
19
- * ### Examples
20
- *
21
- * ```ts
22
- * type HasTwo = TupleIncludes<[1, 2, 3], 2> // true
23
- * type HasFour = TupleIncludes<[1, 2, 3], 4> // false
24
- * ```
25
- */
26
- export type TupleIncludes<Tuple extends readonly unknown[], Element> = Tuple extends readonly [infer First, ...infer Rest] ? (Same<Element, First> extends true ? true : TupleIncludes<Rest, Element>) : false;
27
- /**
28
- * Appends an element to a tuple only if it doesn't already exist in the tuple
29
- *
30
- * ### Examples
31
- *
32
- * ```ts
33
- * type Result1 = AppendUnique<[1, 2, 3], 4> // [1, 2, 3, 4]
34
- * type Result2 = AppendUnique<[1, 2, 3], 2> // [1, 2, 3]
35
- * ```
36
- */
37
- export type AppendUnique<Tuple extends readonly unknown[], Element> = TupleIncludes<Tuple, Element> extends true ? Tuple : [...Tuple, Element];
38
- /**
39
- * Concatenates two tuples while ensuring uniqueness of elements
40
- *
41
- * ### Examples
42
- *
43
- * ```ts
44
- * type Result = ConcatUniqueTuple<[1, 2, 3], [2, 3, 4]> // [1, 2, 3, 4]
45
- * ```
46
- */
47
- export type ConcatUniqueTuple<A extends readonly unknown[], B extends readonly unknown[], R extends readonly unknown[] = A> = B extends readonly [infer First, ...infer Rest] ? ConcatUniqueTuple<A, Rest, AppendUnique<R, First>> : R;
48
- //# sourceMappingURL=array.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/main/array.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAE7C;;GAEG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,OAAO,IAAI,SAAS,CAAC,EAAE,CAAA;AAErD;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW,CACrB,IAAI,SAAS,SAAS,OAAO,EAAE,EAC/B,KAAK,SAAS,SAAS,OAAO,EAAE,IAC9B,IAAI,SAAS,SAAS,OAAO,EAAE,GAAG,CAAC,KAAK,SAAS,SAAS,OAAO,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAA;AAE9G;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,CACvB,KAAK,SAAS,SAAS,OAAO,EAAE,EAChC,OAAO,IACL,KAAK,SAAS,SAAS,CAAC,MAAM,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,GACnD,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,IAAI,GAAG,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,GACzE,KAAK,CAAA;AAET;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,CACtB,KAAK,SAAS,SAAS,OAAO,EAAE,EAChC,OAAO,IACL,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,IAAI,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,CAAA;AAE5E;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,CAC3B,CAAC,SAAS,SAAS,OAAO,EAAE,EAC5B,CAAC,SAAS,SAAS,OAAO,EAAE,EAC5B,CAAC,SAAS,SAAS,OAAO,EAAE,GAAG,CAAC,IAC9B,CAAC,SAAS,SAAS,CAAC,MAAM,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAA"}
package/esm/main/array.js DELETED
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=array.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"array.js","sourceRoot":"","sources":["../../src/main/array.ts"],"names":[],"mappings":"","sourcesContent":["import type { Same } from './type/compare.js'\n\n/**\n * Represents a readonly array of type T\n */\nexport type ReadonlyArray<T = unknown> = readonly T[]\n\n/**\n * Concatenates two tuples into a single tuple type\n *\n * ### Examples\n *\n * ```ts\n * type Result = ConcatTuple<[1, 2], [3, 4]> // [1, 2, 3, 4]\n * ```\n */\nexport type ConcatTuple<\n Left extends readonly unknown[],\n Right extends readonly unknown[],\n> = Left extends readonly unknown[] ? (Right extends readonly unknown[] ? [...Left, ...Right] : never) : never\n\n/**\n * Checks whether a tuple includes a specific element type\n *\n * ### Examples\n *\n * ```ts\n * type HasTwo = TupleIncludes<[1, 2, 3], 2> // true\n * type HasFour = TupleIncludes<[1, 2, 3], 4> // false\n * ```\n */\nexport type TupleIncludes<\n Tuple extends readonly unknown[],\n Element,\n> = Tuple extends readonly [infer First, ...infer Rest]\n ? (Same<Element, First> extends true ? true : TupleIncludes<Rest, Element>)\n : false\n\n/**\n * Appends an element to a tuple only if it doesn't already exist in the tuple\n *\n * ### Examples\n *\n * ```ts\n * type Result1 = AppendUnique<[1, 2, 3], 4> // [1, 2, 3, 4]\n * type Result2 = AppendUnique<[1, 2, 3], 2> // [1, 2, 3]\n * ```\n */\nexport type AppendUnique<\n Tuple extends readonly unknown[],\n Element,\n> = TupleIncludes<Tuple, Element> extends true ? Tuple : [...Tuple, Element]\n\n/**\n * Concatenates two tuples while ensuring uniqueness of elements\n *\n * ### Examples\n *\n * ```ts\n * type Result = ConcatUniqueTuple<[1, 2, 3], [2, 3, 4]> // [1, 2, 3, 4]\n * ```\n */\nexport type ConcatUniqueTuple<\n A extends readonly unknown[],\n B extends readonly unknown[],\n R extends readonly unknown[] = A,\n> = B extends readonly [infer First, ...infer Rest] ? ConcatUniqueTuple<A, Rest, AppendUnique<R, First>> : R\n"]}