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.
- package/README.md +40 -67
- package/esm/main/boolean.d.ts +1 -2
- package/esm/main/boolean.d.ts.map +1 -1
- package/esm/main/boolean.js.map +1 -1
- package/esm/main/control.d.ts +15 -20
- package/esm/main/control.d.ts.map +1 -1
- package/esm/main/control.js.map +1 -1
- package/esm/main/function.d.ts +2 -4
- package/esm/main/function.d.ts.map +1 -1
- package/esm/main/function.js.map +1 -1
- package/esm/main/index.d.ts +1 -1
- package/esm/main/index.d.ts.map +1 -1
- package/esm/main/index.js +3 -1
- package/esm/main/index.js.map +1 -1
- package/esm/main/key.d.ts +53 -17
- package/esm/main/key.d.ts.map +1 -1
- package/esm/main/key.js.map +1 -1
- package/esm/main/object.d.ts +45 -31
- package/esm/main/object.d.ts.map +1 -1
- package/esm/main/object.js.map +1 -1
- package/esm/main/tuple.d.ts +40 -0
- package/esm/main/tuple.d.ts.map +1 -0
- package/esm/main/tuple.js +2 -0
- package/esm/main/tuple.js.map +1 -0
- package/esm/main/type/compare.d.ts +9 -9
- package/esm/main/type/compare.d.ts.map +1 -1
- package/esm/main/type/compare.js.map +1 -1
- package/esm/main/type/index.d.ts.map +1 -1
- package/esm/main/type/index.js +2 -0
- package/esm/main/type/index.js.map +1 -1
- package/esm/main/type/set.d.ts +4 -6
- package/esm/main/type/set.d.ts.map +1 -1
- package/esm/main/type/set.js.map +1 -1
- package/esm/test-utils/compare.d.ts +69 -0
- package/esm/test-utils/compare.d.ts.map +1 -0
- package/esm/test-utils/compare.js +2 -0
- package/esm/test-utils/compare.js.map +1 -0
- package/esm/test-utils/expect.d.ts +223 -0
- package/esm/test-utils/expect.d.ts.map +1 -0
- package/esm/test-utils/expect.js +2 -0
- package/esm/test-utils/expect.js.map +1 -0
- package/esm/test-utils/index.d.ts +72 -0
- package/esm/test-utils/index.d.ts.map +1 -0
- package/esm/{test-utils.js → test-utils/index.js} +5 -5
- package/esm/test-utils/index.js.map +1 -0
- package/package.json +3 -3
- package/script/main/boolean.d.ts +1 -2
- package/script/main/boolean.d.ts.map +1 -1
- package/script/main/boolean.js.map +1 -1
- package/script/main/control.d.ts +15 -20
- package/script/main/control.d.ts.map +1 -1
- package/script/main/control.js.map +1 -1
- package/script/main/function.d.ts +2 -4
- package/script/main/function.d.ts.map +1 -1
- package/script/main/function.js.map +1 -1
- package/script/main/index.d.ts +1 -1
- package/script/main/index.d.ts.map +1 -1
- package/script/main/index.js +3 -1
- package/script/main/index.js.map +1 -1
- package/script/main/key.d.ts +53 -17
- package/script/main/key.d.ts.map +1 -1
- package/script/main/key.js.map +1 -1
- package/script/main/object.d.ts +45 -31
- package/script/main/object.d.ts.map +1 -1
- package/script/main/object.js.map +1 -1
- package/script/main/tuple.d.ts +40 -0
- package/script/main/tuple.d.ts.map +1 -0
- package/script/main/{array.js → tuple.js} +1 -1
- package/script/main/tuple.js.map +1 -0
- package/script/main/type/compare.d.ts +9 -9
- package/script/main/type/compare.d.ts.map +1 -1
- package/script/main/type/compare.js.map +1 -1
- package/script/main/type/index.d.ts.map +1 -1
- package/script/main/type/index.js +2 -0
- package/script/main/type/index.js.map +1 -1
- package/script/main/type/set.d.ts +4 -6
- package/script/main/type/set.d.ts.map +1 -1
- package/script/main/type/set.js.map +1 -1
- package/script/test-utils/compare.d.ts +69 -0
- package/script/test-utils/compare.d.ts.map +1 -0
- package/script/test-utils/compare.js +3 -0
- package/script/test-utils/compare.js.map +1 -0
- package/script/test-utils/expect.d.ts +223 -0
- package/script/test-utils/expect.d.ts.map +1 -0
- package/script/test-utils/expect.js +3 -0
- package/script/test-utils/expect.js.map +1 -0
- package/script/test-utils/index.d.ts +72 -0
- package/script/test-utils/index.d.ts.map +1 -0
- package/script/{test-utils.js → test-utils/index.js} +6 -6
- package/script/test-utils/index.js.map +1 -0
- package/esm/main/array.d.ts +0 -48
- package/esm/main/array.d.ts.map +0 -1
- package/esm/main/array.js +0 -2
- package/esm/main/array.js.map +0 -1
- package/esm/test-utils.d.ts +0 -348
- package/esm/test-utils.d.ts.map +0 -1
- package/esm/test-utils.js.map +0 -1
- package/script/main/array.d.ts +0 -48
- package/script/main/array.d.ts.map +0 -1
- package/script/main/array.js.map +0 -1
- package/script/test-utils.d.ts +0 -348
- package/script/test-utils.d.ts.map +0 -1
- package/script/test-utils.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
[](https://github.com/Leawind/lay-sing?tab=MIT-1-ov-file)
|
|
2
|
+
[](https://www.npmjs.com/package/lay-sing)
|
|
3
|
+
[](https://jsr.io/@leawind/lay-sing)
|
|
4
|
+
[](https://github.com/Leawind/lay-sing/actions/workflows/verify.yaml)
|
|
3
5
|
|
|
4
|
-
#
|
|
6
|
+
# Lay-Sing
|
|
5
7
|
|
|
6
8
|
TypeScript utilities for compile-time type testing and utility types
|
|
7
9
|
|
|
8
|
-
## What is it
|
|
9
|
-
|
|
10
|
-
1. **Testing Utilities**
|
|
11
|
-
|
|
12
10
|
```ts
|
|
13
11
|
// They do nothing at runtime
|
|
14
12
|
expect<never>().toBe<never>().success
|
|
15
|
-
expect<never>().toBeNever // alias for above
|
|
13
|
+
expect<never>().toBeNever // alias for the above
|
|
16
14
|
expect<never>().toBe<'should fail'>().fail
|
|
17
15
|
|
|
18
16
|
// Type Error: Property 'success' does not exist on type '{ fail: void; }'.
|
|
@@ -20,49 +18,24 @@ expect<never>().toBe<'should fail'>().success
|
|
|
20
18
|
// ^^^^^^^
|
|
21
19
|
```
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
// Result is 'Bob'
|
|
27
|
-
type Result = Switch<2, [
|
|
28
|
-
Case<1, 'Alice'>,
|
|
29
|
-
Case<2, 'Bob'>,
|
|
30
|
-
Case<3, 'Charlie'>,
|
|
31
|
-
], DefaultCase<'Unknown'>>
|
|
32
|
-
```
|
|
21
|
+
> [!TIP]
|
|
22
|
+
>
|
|
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.
|
|
33
24
|
|
|
34
25
|
## Install
|
|
35
26
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
### NPM
|
|
27
|
+
### [NPM](https://www.npmjs.com/package/lay-sing)
|
|
39
28
|
|
|
40
29
|
```sh
|
|
41
30
|
npm i -D lay-sing
|
|
42
31
|
```
|
|
43
32
|
|
|
44
33
|
```ts
|
|
45
|
-
import type {
|
|
34
|
+
import type { Exact } from 'lay-sing'
|
|
46
35
|
import { expect } from 'lay-sing/test-utils'
|
|
47
36
|
```
|
|
48
37
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
```sh
|
|
52
|
-
deno add jsr:@leawind/lay-sing
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
```ts
|
|
56
|
-
import type { Same } from '@leawind/lay-sing'
|
|
57
|
-
import { expect } from '@leawind/lay-sing/test-utils'
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
Or Import directly:
|
|
61
|
-
|
|
62
|
-
```ts
|
|
63
|
-
import type { Same } from 'jsr:@leawind/lay-sing@^0.1'
|
|
64
|
-
import { expect } from 'jsr:@leawind/lay-sing@^0.1/test-utils'
|
|
65
|
-
```
|
|
38
|
+
> This library is also published to [JSR (`@leawind/lay-sing`)](https://jsr.io/@leawind/lay-sing)
|
|
66
39
|
|
|
67
40
|
---
|
|
68
41
|
|
|
@@ -74,7 +47,7 @@ import { expect } from 'jsr:@leawind/lay-sing@^0.1/test-utils'
|
|
|
74
47
|
import { compare, expect, NOOP } from 'lay-sing/test-utils'
|
|
75
48
|
```
|
|
76
49
|
|
|
77
|
-
The `test-utils` module provides utilities for **compile-time** type validation. These utilities have **no runtime
|
|
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.
|
|
78
51
|
|
|
79
52
|
A typical type test statement follows this pattern:
|
|
80
53
|
|
|
@@ -84,8 +57,18 @@ expect<ActualType>().toBe<ExpectedType>().success
|
|
|
84
57
|
|
|
85
58
|
- It starts with a function call like `expect<T>()` or `compare<T, U>()`
|
|
86
59
|
- It ends with a property like `.success` or `.fail`
|
|
87
|
-
-
|
|
88
|
-
|
|
60
|
+
- Type error occurs only if the assertion fails
|
|
61
|
+
|
|
62
|
+
> [!CAUTION]
|
|
63
|
+
>
|
|
64
|
+
> Only statements ending with property access are type assertions. Without property access, type error may never occur:
|
|
65
|
+
>
|
|
66
|
+
> ```diff
|
|
67
|
+
> - expect<true>().toBe<false>() // Type error never occur
|
|
68
|
+
> + expect<true>().toBe<false>().success // Type Error: Property 'success' does not exist on type '{ fail: void; }'.
|
|
69
|
+
> ```
|
|
70
|
+
|
|
71
|
+
At runtime, the function always returns the `NOOP` object, which performs **no operation**. It can be accessed, called, or chained indefinitely without throwing errors.
|
|
89
72
|
|
|
90
73
|
#### Common Usage
|
|
91
74
|
|
|
@@ -97,7 +80,7 @@ expect<A>().toBe<B>().success // Passes only if A and B are identical
|
|
|
97
80
|
expect<A>().toExtend<B>().success // Passes if A extends B
|
|
98
81
|
|
|
99
82
|
// Property existence
|
|
100
|
-
expect<{ name: string }>().
|
|
83
|
+
expect<{ name: string }>().toHaveKey<'name'>().success
|
|
101
84
|
|
|
102
85
|
// Primitive checks
|
|
103
86
|
expect<true>().toBeTrue.success
|
|
@@ -108,39 +91,37 @@ compare<A, B>().same // Available only if A ≡ B
|
|
|
108
91
|
compare<A, B>().different // Available only if A ≠ B
|
|
109
92
|
```
|
|
110
93
|
|
|
111
|
-
> [!TIP]
|
|
112
|
-
>
|
|
113
|
-
> There's no need to memorize the full API.
|
|
114
|
-
>
|
|
115
|
-
> Your editor will show inline documentation and auto-completion for all available methods and properties
|
|
116
|
-
|
|
117
94
|
#### NOOP
|
|
118
95
|
|
|
119
|
-
A `Proxy`-based no-op object:
|
|
96
|
+
A `Proxy`-based no-op object with the following behavior:
|
|
120
97
|
|
|
121
|
-
- Most accesses return itself.
|
|
122
|
-
-
|
|
98
|
+
- Most property/method accesses return the NOOP object itself.
|
|
99
|
+
- `.toString()`, `.valueOf()` returns string `"[NOOP]"`.
|
|
123
100
|
- Not thenable (`then` is `undefined`).
|
|
124
101
|
|
|
102
|
+
It's used as returned value of `expect()` and `compare()`.
|
|
103
|
+
|
|
125
104
|
```ts
|
|
126
|
-
|
|
105
|
+
expect().foo.bar().baz.qux // Safe, returns NOOP
|
|
127
106
|
String(NOOP) // "[NOOP]"
|
|
128
|
-
await NOOP //
|
|
107
|
+
await NOOP // Does not await (not thenable)
|
|
129
108
|
```
|
|
130
109
|
|
|
131
110
|
### Type Tools
|
|
132
111
|
|
|
133
|
-
The main entry point provides
|
|
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.
|
|
134
113
|
|
|
135
114
|
```ts
|
|
136
|
-
import type {
|
|
115
|
+
import type { Exact } from 'lay-sing'
|
|
137
116
|
```
|
|
138
117
|
|
|
139
|
-
> All types are documented — your editor will show inline documentation on hover
|
|
140
|
-
|
|
141
118
|
### Examples
|
|
142
119
|
|
|
143
120
|
```typescript
|
|
121
|
+
// Test if exactly the same
|
|
122
|
+
type False = Exact<{ a: 1 }, { a?: 1 }> // false
|
|
123
|
+
type Yes = Exact<boolean, true | false, 'yes', 'no'> // 'yes'
|
|
124
|
+
|
|
144
125
|
// Conditional Types
|
|
145
126
|
type Result = If<true, 'yes', 'no'> // 'yes'
|
|
146
127
|
|
|
@@ -155,12 +136,4 @@ type PartialObj = DeepPartial<{ a: string; nested: { b: number } }>
|
|
|
155
136
|
// { a?: string; nested?: { b?: number } }
|
|
156
137
|
```
|
|
157
138
|
|
|
158
|
-
|
|
159
|
-
>
|
|
160
|
-
> [Full API documentation is available on JSR](https://jsr.io/@leawind/lay-sing/doc)
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
> ## _Pronunciation of lay-sing_
|
|
165
|
-
>
|
|
166
|
-
> _"lay-sing" mimics Mandarin "lèi xíng" ("type") — Say "LAY-sing" with a sharp "LAY" (like a command) followed by a rising "sing" (like a question)._
|
|
139
|
+
[Full API documentation is available on JSR](https://jsr.io/@leawind/lay-sing/doc)
|
package/esm/main/boolean.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boolean.d.ts","sourceRoot":"","sources":["../../src/main/boolean.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"boolean.d.ts","sourceRoot":"","sources":["../../src/main/boolean.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,OAAO,IAAI,CAAC,SAAS,IAAI,GAAG,KAAK,GACvD,CAAC,SAAS,KAAK,GAAG,IAAI,GACtB,OAAO,CAAA;AAEX;;;;;GAKG;AACH,MAAM,MAAM,GAAG,CACb,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,OAAO,IACf,CAAC,SAAS,KAAK,GAAG,KAAK,GACvB,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAC3B,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,CAAC,SAAS,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,CAAA;AAE9D;;;;;;;GAOG;AACH,MAAM,MAAM,EAAE,CACZ,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,OAAO,IACf,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAC3B,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAC3B,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,GAC/B,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,GAC/B,IAAI,SAAS,CAAC,GAAG,IAAI,GACrB,IAAI,SAAS,CAAC,GAAG,IAAI,GACrB,KAAK,CAAA"}
|
package/esm/main/boolean.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boolean.js","sourceRoot":"","sources":["../../src/main/boolean.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * ### Result\n *\n * - `never`: if `T` is `never`\n * - `boolean`: if `T` is `boolean` or `any`\n * - `false`: if `T` is `true`\n * - `true`: if `T` is `false`\n *\n *
|
|
1
|
+
{"version":3,"file":"boolean.js","sourceRoot":"","sources":["../../src/main/boolean.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * ### Result\n *\n * - `never`: if `T` is `never`\n * - `boolean`: if `T` is `boolean` or `any`\n * - `false`: if `T` is `true`\n * - `true`: if `T` is `false`\n *\n * @example\n * | `T` | `Not<T>` |\n * | --------- | --------- |\n * | `never` | `never` |\n * | `true` | `false` |\n * | `false` | `true` |\n * | `boolean` | `boolean` |\n * | `any` | `boolean` |\n */\nexport type Not<T extends boolean> = T extends true ? false\n : T extends false ? true\n : boolean\n\n/**\n * - `never`: if anyone of A,B is `never`\n * - `boolean`: if anyone of A,B is `boolean` or `any`\n * - `true`: if both A,B are `true`\n * - `false`: otherwise\n */\nexport type And<\n A extends boolean,\n B extends boolean,\n> = A extends never ? never\n : [B] extends [never] ? never\n : (A extends true ? (B extends true ? true : false) : false)\n\n/**\n * ### Result\n *\n * - `never`: if anyone of A,B is `never`\n * - `boolean`: if anyone of A,B is `boolean` or `any`\n * - `false`: if both A,B are `false`\n * - `true`: otherwise\n */\nexport type Or<\n A extends boolean,\n B extends boolean,\n> = [A] extends [never] ? never\n : [B] extends [never] ? never\n : [boolean] extends [A] ? boolean\n : [boolean] extends [B] ? boolean\n : true extends A ? true\n : true extends B ? true\n : false\n"]}
|
package/esm/main/control.d.ts
CHANGED
|
@@ -1,54 +1,51 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Exact } from './type/compare.js';
|
|
2
2
|
/**
|
|
3
3
|
* Conditional type - returns `T` if condition `C` is true, otherwise returns `F`
|
|
4
4
|
*
|
|
5
5
|
* ### Result
|
|
6
6
|
*
|
|
7
7
|
* - `never`: if `C` is `never`
|
|
8
|
-
* - `
|
|
9
|
-
* - `
|
|
10
|
-
*
|
|
11
|
-
* ### Examples
|
|
8
|
+
* - `Yes`: if `C` is `true`
|
|
9
|
+
* - `No`: if `C` is `false`
|
|
12
10
|
*
|
|
11
|
+
* @example
|
|
13
12
|
* ```ts
|
|
14
13
|
* type Result = If<true, 'yes', 'no'> // 'yes'
|
|
15
14
|
* type Result2 = If<false, 'yes', 'no'> // 'no'
|
|
16
15
|
* type NeverResult = If<never, 'yes', 'no'> // never
|
|
17
16
|
* ```
|
|
18
17
|
*/
|
|
19
|
-
export type If<
|
|
18
|
+
export type If<Condition extends boolean, Yes, No = never> = [Condition] extends [never] ? never : Condition extends true ? Yes : No;
|
|
20
19
|
/**
|
|
21
20
|
* Conditional type - returns `T` if condition `C` is false, otherwise returns `F`
|
|
22
21
|
*
|
|
23
22
|
* ### Result
|
|
24
23
|
*
|
|
25
24
|
* - `never`: if `C` is `never`
|
|
26
|
-
* - `
|
|
27
|
-
* - `
|
|
28
|
-
*
|
|
29
|
-
* ### Examples
|
|
25
|
+
* - `Yes`: if `C` is `false`
|
|
26
|
+
* - `No`: if `C` is `true`
|
|
30
27
|
*
|
|
28
|
+
* @example
|
|
31
29
|
* ```ts
|
|
32
30
|
* type Result = IfFalse<false, 'yes', 'no'> // 'yes'
|
|
33
31
|
* type Result2 = IfFalse<true, 'yes', 'no'> // 'no'
|
|
34
32
|
* type NeverResult = IfFalse<never, 'yes', 'no'> // never
|
|
35
33
|
* ```
|
|
36
34
|
*/
|
|
37
|
-
export type IfFalse<
|
|
35
|
+
export type IfFalse<Condition extends boolean, Yes, No = never> = [Condition] extends [never] ? never : Condition extends false ? Yes : No;
|
|
38
36
|
/**
|
|
39
37
|
* Used with:
|
|
40
38
|
* - {@link Switch}
|
|
41
39
|
* - {@link SwitchExtends}
|
|
42
40
|
*/
|
|
43
|
-
export type Case<T = unknown,
|
|
41
|
+
export type Case<T = unknown, Result = unknown> = [T, Result];
|
|
44
42
|
/**
|
|
45
43
|
* Used with:
|
|
46
44
|
*
|
|
47
45
|
* - {@link Switch}
|
|
48
46
|
* - {@link SwitchExtends}
|
|
49
47
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
48
|
+
* @example
|
|
52
49
|
* ```ts
|
|
53
50
|
* type NameMap<id> = Switch<id, [
|
|
54
51
|
* Case<1, 'Alice'>,
|
|
@@ -59,8 +56,7 @@ export type Case<T = unknown, Return = unknown> = [T, Return];
|
|
|
59
56
|
*/
|
|
60
57
|
export type DefaultCase<T> = T;
|
|
61
58
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
59
|
+
* @example
|
|
64
60
|
* ```ts
|
|
65
61
|
* type Result = Switch<2, [
|
|
66
62
|
* Case<1, 'Alice'>,
|
|
@@ -71,12 +67,11 @@ export type DefaultCase<T> = T;
|
|
|
71
67
|
* // Result: 'Bob'
|
|
72
68
|
* ```
|
|
73
69
|
*/
|
|
74
|
-
export type Switch<T, Cases extends readonly Case[], Default = never> = Cases extends [infer First, ...infer Rest] ? (First extends [infer
|
|
70
|
+
export type Switch<T, Cases extends readonly Case[], Default = never> = Cases extends [infer First, ...infer Rest] ? (First extends [infer Condition, infer Result] ? (Exact<T, Condition> extends true ? Result : (Switch<T, Rest extends readonly Case[] ? Rest : never, Default>)) : (never)) : Default;
|
|
75
71
|
/**
|
|
76
|
-
* Switch type that uses 'extends' logic instead of '
|
|
72
|
+
* Switch type that uses 'extends' logic instead of 'Exact' logic
|
|
77
73
|
*
|
|
78
|
-
*
|
|
79
|
-
* ```ts
|
|
74
|
+
* @example ```ts
|
|
80
75
|
* type Result = SwitchExtends<string | number, [
|
|
81
76
|
* Case<string, 'string type'>,
|
|
82
77
|
* Case<number, 'number type'>,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control.d.ts","sourceRoot":"","sources":["../../src/main/control.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"control.d.ts","sourceRoot":"","sources":["../../src/main/control.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE9C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,EAAE,CACZ,SAAS,SAAS,OAAO,EACzB,GAAG,EACH,EAAE,GAAG,KAAK,IACR,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GACnC,SAAS,SAAS,IAAI,GAAG,GAAG,GAC5B,EAAE,CAAA;AAEN;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,OAAO,CACjB,SAAS,SAAS,OAAO,EACzB,GAAG,EACH,EAAE,GAAG,KAAK,IACR,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GACnC,SAAS,SAAS,KAAK,GAAG,GAAG,GAC7B,EAAE,CAAA;AAEN;;;;GAIG;AACH,MAAM,MAAM,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,GAAG,OAAO,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;AAE7D;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,CAAA;AAE9B;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,MAAM,CAChB,CAAC,EACD,KAAK,SAAS,SAAS,IAAI,EAAE,EAC7B,OAAO,GAAG,KAAK,IACb,KAAK,SAAS,CAAC,MAAM,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAC7C,KAAK,SAAS,CAAC,MAAM,SAAS,EAAE,MAAM,MAAM,CAAC,GACzC,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,IAAI,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,SAAS,SAAS,IAAI,EAAE,GAAG,IAAI,GAAG,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GAC/G,CAAC,KAAK,CAAC,CACZ,GACC,OAAO,CAAA;AAEX;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,CACvB,CAAC,EACD,KAAK,SAAS,SAAS,IAAI,EAAE,EAC7B,OAAO,GAAG,KAAK,IACb,KAAK,SAAS,CAAC,MAAM,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAC7C,KAAK,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,GAC5B,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,IAAI,SAAS,SAAS,IAAI,EAAE,GAAG,IAAI,GAAG,KAAK,EAAE,OAAO,CAAC,CAAC,GAC9F,KAAK,CACV,GACC,OAAO,CAAA"}
|
package/esm/main/control.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control.js","sourceRoot":"","sources":["../../src/main/control.ts"],"names":[],"mappings":"","sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"control.js","sourceRoot":"","sources":["../../src/main/control.ts"],"names":[],"mappings":"","sourcesContent":["import type { Exact } from './type/compare.js'\n\n/**\n * Conditional type - returns `T` if condition `C` is true, otherwise returns `F`\n *\n * ### Result\n *\n * - `never`: if `C` is `never`\n * - `Yes`: if `C` is `true`\n * - `No`: if `C` is `false`\n *\n * @example\n * ```ts\n * type Result = If<true, 'yes', 'no'> // 'yes'\n * type Result2 = If<false, 'yes', 'no'> // 'no'\n * type NeverResult = If<never, 'yes', 'no'> // never\n * ```\n */\nexport type If<\n Condition extends boolean,\n Yes,\n No = never,\n> = [Condition] extends [never] ? never\n : Condition extends true ? Yes\n : No\n\n/**\n * Conditional type - returns `T` if condition `C` is false, otherwise returns `F`\n *\n * ### Result\n *\n * - `never`: if `C` is `never`\n * - `Yes`: if `C` is `false`\n * - `No`: if `C` is `true`\n *\n * @example\n * ```ts\n * type Result = IfFalse<false, 'yes', 'no'> // 'yes'\n * type Result2 = IfFalse<true, 'yes', 'no'> // 'no'\n * type NeverResult = IfFalse<never, 'yes', 'no'> // never\n * ```\n */\nexport type IfFalse<\n Condition extends boolean,\n Yes,\n No = never,\n> = [Condition] extends [never] ? never\n : Condition extends false ? Yes\n : No\n\n/**\n * Used with:\n * - {@link Switch}\n * - {@link SwitchExtends}\n */\nexport type Case<T = unknown, Result = unknown> = [T, Result]\n\n/**\n * Used with:\n *\n * - {@link Switch}\n * - {@link SwitchExtends}\n *\n * @example\n * ```ts\n * type NameMap<id> = Switch<id, [\n * Case<1, 'Alice'>,\n * Case<2, 'Bob'>,\n * Case<3, 'Charlie'>,\n * ], DefaultCase<'Steve'>>\n * ```\n */\nexport type DefaultCase<T> = T\n\n/**\n * @example\n * ```ts\n * type Result = Switch<2, [\n * Case<1, 'Alice'>,\n * Case<2, 'Bob'>,\n * Case<3, 'Charlie'>,\n * ], DefaultCase<'Steve'>>\n *\n * // Result: 'Bob'\n * ```\n */\nexport type Switch<\n T,\n Cases extends readonly Case[],\n Default = never,\n> = Cases extends [infer First, ...infer Rest] ? (\n First extends [infer Condition, infer Result]\n ? (Exact<T, Condition> extends true ? Result : (Switch<T, Rest extends readonly Case[] ? Rest : never, Default>))\n : (never)\n )\n : Default\n\n/**\n * Switch type that uses 'extends' logic instead of 'Exact' logic\n *\n * @example ```ts\n * type Result = SwitchExtends<string | number, [\n * Case<string, 'string type'>,\n * Case<number, 'number type'>,\n * ], 'other'>\n * // Result: 'string type' | 'number type'\n * ```\n */\nexport type SwitchExtends<\n T,\n Cases extends readonly Case[],\n Default = never,\n> = Cases extends [infer First, ...infer Rest] ? (\n First extends [infer C, infer R]\n ? ([T] extends [C] ? R : SwitchExtends<T, Rest extends readonly Case[] ? Rest : never, Default>)\n : never\n )\n : Default\n"]}
|
package/esm/main/function.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Represents a function with any parameters and a specific return type
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* @example
|
|
6
5
|
* ```ts
|
|
7
6
|
* type _ = AnyFunction<string, [number]> // (arg: number) => string
|
|
8
7
|
* ```
|
|
@@ -11,8 +10,7 @@ export type AnyFunction<Return = any, Params extends any[] = any[]> = (...args:
|
|
|
11
10
|
/**
|
|
12
11
|
* Represents a constructor with any parameters and a specific return type
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* @example
|
|
16
14
|
* ```ts
|
|
17
15
|
* type _ = Constructor<string, [number]> // new (arg: number) => string
|
|
18
16
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"function.d.ts","sourceRoot":"","sources":["../../src/main/function.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"function.d.ts","sourceRoot":"","sources":["../../src/main/function.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,CACrB,MAAM,GAAG,GAAG,EACZ,MAAM,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,IAC1B,CAAC,GAAG,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;AAE/B;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,CACrB,MAAM,GAAG,GAAG,EACZ,MAAM,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,IAC1B,KAAK,GAAG,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA"}
|
package/esm/main/function.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"function.js","sourceRoot":"","sources":["../../src/main/function.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["// deno-lint-ignore-file no-explicit-any\n\n/**\n * Represents a function with any parameters and a specific return type\n *\n *
|
|
1
|
+
{"version":3,"file":"function.js","sourceRoot":"","sources":["../../src/main/function.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["// deno-lint-ignore-file no-explicit-any\n\n/**\n * Represents a function with any parameters and a specific return type\n *\n * @example\n * ```ts\n * type _ = AnyFunction<string, [number]> // (arg: number) => string\n * ```\n */\nexport type AnyFunction<\n Return = any,\n Params extends any[] = any[],\n> = (...args: Params) => Return\n\n/**\n * Represents a constructor with any parameters and a specific return type\n *\n * @example\n * ```ts\n * type _ = Constructor<string, [number]> // new (arg: number) => string\n * ```\n */\nexport type Constructor<\n Return = any,\n Params extends any[] = any[],\n> = new (...args: Params) => Return\n"]}
|
package/esm/main/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export * from './array.js';
|
|
2
1
|
export * from './async.js';
|
|
3
2
|
export * from './boolean.js';
|
|
4
3
|
export * from './control.js';
|
|
@@ -7,6 +6,7 @@ export * from './function.js';
|
|
|
7
6
|
export * from './json.js';
|
|
8
7
|
export * from './key.js';
|
|
9
8
|
export * from './object.js';
|
|
9
|
+
export * from './tuple.js';
|
|
10
10
|
export * from './type/index.js';
|
|
11
11
|
export * from './typed-array.js';
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|
package/esm/main/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/main/index.ts"],"names":[],"mappings":"
|
|
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"}
|
package/esm/main/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// Index start >>>>>>>>>>>>>>>>
|
|
2
2
|
export * from './async.js';
|
|
3
3
|
export * from './boolean.js';
|
|
4
4
|
export * from './control.js';
|
|
@@ -7,6 +7,8 @@ export * from './function.js';
|
|
|
7
7
|
export * from './json.js';
|
|
8
8
|
export * from './key.js';
|
|
9
9
|
export * from './object.js';
|
|
10
|
+
export * from './tuple.js';
|
|
10
11
|
export * from './type/index.js';
|
|
11
12
|
export * from './typed-array.js';
|
|
13
|
+
// <<<<<<<<<<<<<<<< Index end
|
|
12
14
|
//# sourceMappingURL=index.js.map
|
package/esm/main/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/main/index.ts"],"names":[],"mappings":"AAAA
|
|
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"]}
|
package/esm/main/key.d.ts
CHANGED
|
@@ -1,26 +1,62 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Exact } from './type/index.js';
|
|
2
2
|
/**
|
|
3
|
-
* Extracts the keys of type
|
|
3
|
+
* Extracts the keys of an object whose **base value type** matches the specified `ValueType` (ignoring undefined from optional properties).
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* This utility matches the underlying/base type of each property (stripping `undefined` added by optional modifiers `?`).
|
|
6
|
+
* For optional properties (e.g., `a?: string`), the type is treated as `string` – no need to include `undefined` in `ValueType` to match.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
* type
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* @template Obj - The target object type to extract keys from.
|
|
9
|
+
* @template ValueType - The base type to match against property values (ignoring undefined from optional properties).
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Basic usage: match base type (non-optional property)
|
|
13
|
+
* type A = { a: 1; b: 2; c: 1 };
|
|
14
|
+
* type MatchedKeys = KeysOfBaseType<A, 1>; // 'a' | 'c'
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Key difference: optional property matching (ignores undefined)
|
|
18
|
+
* type B = { a?: string; b: string };
|
|
19
|
+
* type MatchBaseString = KeysOfBaseType<B, string>; // 'a' | 'b' (matches base type of both)
|
|
20
|
+
* type MatchWithUndefined = KeysOfBaseType<B, string | undefined>; // never (base type does not include undefined)
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Edge cases: never/any/unknown
|
|
24
|
+
* type C = { a: never; b: any; c: unknown };
|
|
25
|
+
* type MatchNever = KeysOfBaseType<C, never>; // 'a'
|
|
26
|
+
* type MatchAny = KeysOfBaseType<C, any>; // 'b'
|
|
27
|
+
* type MatchUnknown = KeysOfBaseType<C, unknown>; // 'c'
|
|
11
28
|
*/
|
|
12
|
-
export type
|
|
13
|
-
[K in keyof
|
|
14
|
-
}[keyof
|
|
29
|
+
export type KeysOfBaseType<Obj, ValueType> = Exclude<{
|
|
30
|
+
[K in keyof Obj]: Exact<Required<Obj>[K], ValueType> extends true ? K : never;
|
|
31
|
+
}[keyof Obj], undefined>;
|
|
15
32
|
/**
|
|
16
|
-
* Extracts the keys of type
|
|
33
|
+
* Extracts the keys of an object whose **complete value type** exactly matches the specified `ValueType` (including undefined for optional properties).
|
|
34
|
+
*
|
|
35
|
+
* This utility strictly matches the full type of each property (including `undefined` added by optional modifiers `?`).
|
|
36
|
+
* For optional properties (e.g., `a?: string`), the type is treated as `string | undefined` – to match, `ValueType` must include `undefined`.
|
|
37
|
+
*
|
|
38
|
+
* @template Obj - The target object type to extract keys from.
|
|
39
|
+
* @template ValueType - The exact type to match against property values (including undefined for optional properties).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // Basic usage: match exact type (non-optional property)
|
|
43
|
+
* type A = { a: 1; b: 2; c: 1 };
|
|
44
|
+
* type MatchedKeys = KeysOfExactType<A, 1>; // 'a' | 'c'
|
|
17
45
|
*
|
|
18
|
-
*
|
|
46
|
+
* @example
|
|
47
|
+
* // Key difference: optional property matching (requires undefined in `ValueType`)
|
|
48
|
+
* type B = { a?: string };
|
|
49
|
+
* type MatchWithUndefined = KeysOfExactType<B, string | undefined>; // 'a' (matches complete type)
|
|
50
|
+
* type MatchWithoutUndefined = KeysOfExactType<B, string>; // never (does not match complete type)
|
|
19
51
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* type
|
|
23
|
-
*
|
|
52
|
+
* @example
|
|
53
|
+
* // Edge cases: never/any/unknown
|
|
54
|
+
* type C = { a: never; b: any; c: unknown };
|
|
55
|
+
* type MatchNever = KeysOfExactType<C, never>; // 'a'
|
|
56
|
+
* type MatchAny = KeysOfExactType<C, any>; // 'b'
|
|
57
|
+
* type MatchUnknown = KeysOfExactType<C, unknown>; // 'c'
|
|
24
58
|
*/
|
|
25
|
-
export type
|
|
59
|
+
export type KeysOfExactType<Obj, ValueType> = Exclude<{
|
|
60
|
+
[K in keyof Obj]: Exact<Obj[K], ValueType> extends true ? K : never;
|
|
61
|
+
}[keyof Obj], undefined>;
|
|
26
62
|
//# sourceMappingURL=key.d.ts.map
|
package/esm/main/key.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../../src/main/key.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../../src/main/key.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,MAAM,cAAc,CAAC,GAAG,EAAE,SAAS,IAAI,OAAO,CAClD;KACG,CAAC,IAAI,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK;CAC9E,CAAC,MAAM,GAAG,CAAC,EACZ,SAAS,CACV,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,MAAM,eAAe,CAAC,GAAG,EAAE,SAAS,IAAI,OAAO,CACnD;KAAG,CAAC,IAAI,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK;CAAE,CAAC,MAAM,GAAG,CAAC,EAClF,SAAS,CACV,CAAA"}
|
package/esm/main/key.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"key.js","sourceRoot":"","sources":["../../src/main/key.ts"],"names":[],"mappings":"","sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"key.js","sourceRoot":"","sources":["../../src/main/key.ts"],"names":[],"mappings":"","sourcesContent":["import type { Exact } from './type/index.js'\n\n/**\n * Extracts the keys of an object whose **base value type** matches the specified `ValueType` (ignoring undefined from optional properties).\n *\n * This utility matches the underlying/base type of each property (stripping `undefined` added by optional modifiers `?`).\n * For optional properties (e.g., `a?: string`), the type is treated as `string` – no need to include `undefined` in `ValueType` to match.\n *\n * @template Obj - The target object type to extract keys from.\n * @template ValueType - The base type to match against property values (ignoring undefined from optional properties).\n *\n * @example\n * // Basic usage: match base type (non-optional property)\n * type A = { a: 1; b: 2; c: 1 };\n * type MatchedKeys = KeysOfBaseType<A, 1>; // 'a' | 'c'\n *\n * @example\n * // Key difference: optional property matching (ignores undefined)\n * type B = { a?: string; b: string };\n * type MatchBaseString = KeysOfBaseType<B, string>; // 'a' | 'b' (matches base type of both)\n * type MatchWithUndefined = KeysOfBaseType<B, string | undefined>; // never (base type does not include undefined)\n *\n * @example\n * // Edge cases: never/any/unknown\n * type C = { a: never; b: any; c: unknown };\n * type MatchNever = KeysOfBaseType<C, never>; // 'a'\n * type MatchAny = KeysOfBaseType<C, any>; // 'b'\n * type MatchUnknown = KeysOfBaseType<C, unknown>; // 'c'\n */\nexport type KeysOfBaseType<Obj, ValueType> = Exclude<\n {\n [K in keyof Obj]: Exact<Required<Obj>[K], ValueType> extends true ? K : never\n }[keyof Obj],\n undefined\n>\n\n/**\n * Extracts the keys of an object whose **complete value type** exactly matches the specified `ValueType` (including undefined for optional properties).\n *\n * This utility strictly matches the full type of each property (including `undefined` added by optional modifiers `?`).\n * For optional properties (e.g., `a?: string`), the type is treated as `string | undefined` – to match, `ValueType` must include `undefined`.\n *\n * @template Obj - The target object type to extract keys from.\n * @template ValueType - The exact type to match against property values (including undefined for optional properties).\n *\n * @example\n * // Basic usage: match exact type (non-optional property)\n * type A = { a: 1; b: 2; c: 1 };\n * type MatchedKeys = KeysOfExactType<A, 1>; // 'a' | 'c'\n *\n * @example\n * // Key difference: optional property matching (requires undefined in `ValueType`)\n * type B = { a?: string };\n * type MatchWithUndefined = KeysOfExactType<B, string | undefined>; // 'a' (matches complete type)\n * type MatchWithoutUndefined = KeysOfExactType<B, string>; // never (does not match complete type)\n *\n * @example\n * // Edge cases: never/any/unknown\n * type C = { a: never; b: any; c: unknown };\n * type MatchNever = KeysOfExactType<C, never>; // 'a'\n * type MatchAny = KeysOfExactType<C, any>; // 'b'\n * type MatchUnknown = KeysOfExactType<C, unknown>; // 'c'\n */\nexport type KeysOfExactType<Obj, ValueType> = Exclude<\n { [K in keyof Obj]: Exact<Obj[K], ValueType> extends true ? K : never }[keyof Obj],\n undefined\n>\n"]}
|