ts-type 3.0.10 → 3.0.13

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/CHANGELOG.md CHANGED
@@ -3,6 +3,64 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.0.13](https://github.com/bluelovers/ws-ts-type/compare/ts-type@3.0.12...ts-type@3.0.13) (2026-03-31)
7
+
8
+
9
+
10
+ ### ✨ Features
11
+
12
+ * **ts-type:** add advanced key filtering and member extraction types ([bee21a9](https://github.com/bluelovers/ws-ts-type/commit/bee21a97560a9c58dc8208a90166544054fc3809))
13
+
14
+
15
+ ### 🛠 Build System
16
+
17
+ * **release:** publish ([26936b2](https://github.com/bluelovers/ws-ts-type/commit/26936b2d770aaf20636d4f79e682b68314b4b926))
18
+
19
+
20
+ ### 🔖 Miscellaneous
21
+
22
+ * . ([cd29157](https://github.com/bluelovers/ws-ts-type/commit/cd29157bc14de461549af02e6619185666e500f9))
23
+ * . ([6c6082f](https://github.com/bluelovers/ws-ts-type/commit/6c6082f9dbd69f86a69cda44bfa3fea3bae1d15b))
24
+
25
+
26
+
27
+ ## [3.0.12](https://github.com/bluelovers/ws-ts-type/compare/ts-type@3.0.10...ts-type@3.0.12) (2026-03-28)
28
+
29
+
30
+
31
+ ### 📚 Documentation
32
+
33
+ * 刪除 WebStorm CLI、MCP 文檔及對比文檔 ([261b92d](https://github.com/bluelovers/ws-ts-type/commit/261b92d41c26766282ec13c2c189836ad5083b51))
34
+ * **ts-type:** 為 ITSPickAndPartialOther 和 ITSPropertyKeyOrIndex 添加 JSDoc 註解與使用範例 ([91a189e](https://github.com/bluelovers/ws-ts-type/commit/91a189e391c029153ddfbc1656a9afa212a5ac35))
35
+
36
+
37
+ ### 🛠 Build System
38
+
39
+ * **ts-type:** set `module` to `node16` in `tsconfig.check.json` ([c615a46](https://github.com/bluelovers/ws-ts-type/commit/c615a463a8552657993d698a69dbcb541b1ff4d3))
40
+
41
+
42
+ ### 🔖 Miscellaneous
43
+
44
+ * . ([ac97bcd](https://github.com/bluelovers/ws-ts-type/commit/ac97bcde04dc40f354b24e29052b6f04ad7f1687))
45
+
46
+
47
+
48
+ ## [3.0.11](https://github.com/bluelovers/ws-ts-type/compare/ts-type@3.0.10...ts-type@3.0.11) (2026-03-28)
49
+
50
+
51
+
52
+ ### 📚 Documentation
53
+
54
+ * 刪除 WebStorm CLI、MCP 文檔及對比文檔 ([261b92d](https://github.com/bluelovers/ws-ts-type/commit/261b92d41c26766282ec13c2c189836ad5083b51))
55
+ * **ts-type:** 為 ITSPickAndPartialOther 和 ITSPropertyKeyOrIndex 添加 JSDoc 註解與使用範例 ([91a189e](https://github.com/bluelovers/ws-ts-type/commit/91a189e391c029153ddfbc1656a9afa212a5ac35))
56
+
57
+
58
+ ### 🛠 Build System
59
+
60
+ * **ts-type:** set `module` to `node16` in `tsconfig.check.json` ([c615a46](https://github.com/bluelovers/ws-ts-type/commit/c615a463a8552657993d698a69dbcb541b1ff4d3))
61
+
62
+
63
+
6
64
  ## [3.0.10](https://github.com/bluelovers/ws-ts-type/compare/ts-type@3.0.8...ts-type@3.0.10) (2026-03-15)
7
65
 
8
66
 
@@ -89,3 +89,168 @@ export type ITSKeyofBothSame<T, U> = ITSKeyofSame<T, U> | ITSKeyofSame<U, T>;
89
89
  * type Result = ITSKeyofBothDiff<A, B>; // 'b' | 'c'
90
90
  */
91
91
  export type ITSKeyofBothDiff<T, U> = ITSKeyofDiff<T, U> | ITSKeyofDiff<U, T>;
92
+ /**
93
+ * ITSFilterKeysString - 基礎鍵過濾類型
94
+ * 從聯合類型中排除指定的字符串鍵
95
+ *
96
+ * 使用範例:
97
+ * @example
98
+ * type AllKeys = 'log' | 'debug' | 'constructor' | 'error';
99
+ * type PublicKeys = ITSFilterKeysString<AllKeys, 'constructor'>; // 'log' | 'debug' | 'error'
100
+ * type SafeKeys = ITSFilterKeysString<AllKeys, 'constructor' | 'error'>; // 'log' | 'debug'
101
+ *
102
+ * @example
103
+ * type ITSFilterKeysString<T, ExcludeKeys extends string = never> = T extends infer U
104
+ * ? U extends string
105
+ * ? U extends ExcludeKeys ? never : U
106
+ * : never
107
+ * : never;
108
+ *
109
+ * @see ITSExcludeFilterKeys
110
+ */
111
+ export type ITSExcludeFilterKeysString<T, ExcludeKeys extends string = never> = ITSExcludeFilterKeys<T, ExcludeKeys, string>;
112
+ /**
113
+ * ITSFilterKeysPropertyKey - 支持 PropertyKey(string | number | symbol)的版本
114
+ *
115
+ * 使用範例:
116
+ * @example
117
+ * type AllKeys = 'log' | 'debug' | 'constructor' | 42 | symbol;
118
+ * type StringKeys = ITSFilterKeysPropertyKey<AllKeys, number | symbol>; // 'log' | 'debug' | 'constructor'
119
+ * type NoSymbol = ITSFilterKeysPropertyKey<AllKeys, symbol>; // 'log' | 'debug' | 'constructor' | 42
120
+ *
121
+ * @example
122
+ * type ITSFilterKeysPropertyKey<T, ExcludeKeys extends PropertyKey = never> = T extends infer U
123
+ * ? U extends PropertyKey
124
+ * ? U extends ExcludeKeys ? never : U
125
+ * : never
126
+ * : never;
127
+ *
128
+ * @see ITSExcludeFilterKeys
129
+ */
130
+ export type ITSExcludeFilterKeysPropertyKey<T, ExcludeKeys extends PropertyKey = never> = ITSExcludeFilterKeys<T, ExcludeKeys, PropertyKey>;
131
+ /**
132
+ * ITSFilterKeys - 可配置鍵類型範圍的版本
133
+ * 第三個類型參數 `AllowedPropertyKey` 允許精確控制保留哪些類型的鍵
134
+ *
135
+ * 使用範例:
136
+ * @example
137
+ * ```
138
+ * type AllKeys = 'log' | 'debug' | 42 | 99 | symbol;
139
+ *
140
+ * // 只保留 string 類型,排除 'log'
141
+ * type StringOnly = ITSFilterKeys<AllKeys, 'log', string>; // 'debug'
142
+ *
143
+ * // 只保留 number 類型,不排除任何鍵
144
+ * type NumOnly = ITSFilterKeys<AllKeys, never, number>; // 42 | 99
145
+ *
146
+ * // 保留 string | number,排除 'debug'
147
+ * type Mixed = ITSFilterKeys<AllKeys, 'debug', string | number>; // 'log' | 42 | 99
148
+ * ```
149
+ *
150
+ * 三代版本對比:
151
+ * ITSFilterKeysString: 固定處理 string(最基礎)
152
+ * ITSFilterKeysPropertyKey: 固定處理 PropertyKey(更廣泛)
153
+ * ITSFilterKeys: 可配置 AllowedPropertyKey 參數(最靈活)
154
+ *
155
+ * @see ITSExtractKeysV13
156
+ */
157
+ export type ITSExcludeFilterKeys<T, ExcludeKeys extends PropertyKey = never, AllowedPropertyKey extends PropertyKey = PropertyKey> = T extends infer U ? U extends AllowedPropertyKey ? U extends ExcludeKeys ? never : U : never : never;
158
+ /**
159
+ * ITSExtractKeysV13 - 選擇器版本(只保留匹配 IncludeKeys 的鍵)
160
+ *
161
+ * 與 FilterKeysV3 的邏輯差異:
162
+ * - FilterKeysV3: `U extends ExcludeKeys ? never : U` → 排除匹配的鍵
163
+ * - ITSExtractKeysV13: `U extends IncludeKeys ? U : never` → 只保留匹配的鍵
164
+ *
165
+ * 設計理念:
166
+ * ---------------------------
167
+ * ExtractKeyofV12 系列的核心需求是「篩選符合 V 類型的鍵」。
168
+ * FilterKeys 系列的設計是「排除」思維( ExcludeKeys ),
169
+ * 而 ITSExtractKeysV13 採用「選擇」思維( IncludeKeys ),更符合鍵提取的語義。
170
+ *
171
+ * 與 FilterKeysV3 實作的對比:
172
+ * - FilterKeysV3: `FilterKeysV3<T, never, V>`(用 AllowedPropertyKey 篩選,ExcludeKeys 設為 never)
173
+ * - ITSExtractKeysV13: `ITSExtractKeysV13<T, V, PropertyKey>`(直接用 IncludeKeys 篩選)
174
+ *
175
+ * 使用範例與測試驗證:
176
+ * ```typescript
177
+ * type AllKeys = 'log' | 'debug' | 'error' | 42 | 99 | symbol;
178
+ *
179
+ * // 1. 篩選 string 類型鍵(等同 ExtractKeyofV12d<AllKeys, string>)
180
+ * // ✅ 結果:'log' | 'debug' | 'error'
181
+ * type Strings = ITSExtractKeysV13<AllKeys, string, PropertyKey>;
182
+ *
183
+ * // 2. 篩選 number 類型鍵
184
+ * // ✅ 結果:42 | 99
185
+ * type Numbers = ITSExtractKeysV13<AllKeys, number, PropertyKey>;
186
+ *
187
+ * // 3. 只保留特定字面量
188
+ * // ✅ 結果:'log' | 'debug'
189
+ * type Picked = ITSExtractKeysV13<AllKeys, 'log' | 'debug', PropertyKey>;
190
+ *
191
+ * // 4. 特定數字字面量(只保留 42,過濾 99)
192
+ * // ✅ 結果:42
193
+ * // ❌ 99 會被過濾
194
+ * type SpecificNumber = ITSExtractKeysV13<AllKeys, 42, PropertyKey>;
195
+ *
196
+ * // 5. 實作 ExtractKeyofV12(輸出轉為 string)
197
+ * // ✅ 結果:'log' | 'debug' | 'error'
198
+ * type V12_Strings = ITSExtractKeysV13<AllKeys, string, PropertyKey> & string;
199
+ *
200
+ * // 6. 限制輸入類型為 string(等同 FilterKeysV3<AllKeys, never, string>)
201
+ * // ✅ 結果:'log' | 'debug' | 'error'
202
+ * // ❌ number/symbol 被過濾
203
+ * type StringOnly = ITSExtractKeysV13<AllKeys, PropertyKey, string>;
204
+ *
205
+ * // 7. symbol 類型篩選(結果為 never)
206
+ * // ✅ 結果:never(symbol 無法通過 PropertyKey 匹配 string/number)
207
+ * type SymbolFiltered = ITSExtractKeysV13<AllKeys, symbol, PropertyKey>;
208
+ * ```
209
+ *
210
+ * Enum 類型處理範例:
211
+ * ------------------
212
+ * TypeScript enum 作為類型時,需使用模板字面量 `${Enum}` 或 keyof typeof 獲取成員。
213
+ *
214
+ * ```typescript
215
+ * enum LogLevel {
216
+ * DEBUG = 'debug',
217
+ * INFO = 'info',
218
+ * WARN = 'warn',
219
+ * ERROR = 'error'
220
+ * }
221
+ *
222
+ * enum StatusCode {
223
+ * OK = 200,
224
+ * NOT_FOUND = 404,
225
+ * ERROR = 500
226
+ * }
227
+ *
228
+ * // 8. 從 enum 鍵中篩選(使用 keyof typeof)
229
+ * // ✅ 結果:'DEBUG' | 'INFO'
230
+ * type EnumKeys = keyof typeof LogLevel; // 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'
231
+ * type PickedEnumKeys = ITSExtractKeysV13<EnumKeys, 'DEBUG' | 'INFO', PropertyKey>;
232
+ *
233
+ * // 11. 數字 enum 的值篩選(使用 infer 提取數字)
234
+ * // ✅ 結果:200 | 500
235
+ * type StatusEnumValues = `${StatusCode}` extends `${infer N extends number}` ? N : never;
236
+ * type PickedStatusValues = ITSExtractKeysV13<200 | 404 | 500, StatusEnumValues, PropertyKey>;
237
+ *
238
+ * // 12. enum 作為第二參數(IncludeKeys)使用 ITSTypeAndStringLiteral
239
+ * // 搭配 ts-type 的 ITSTypeAndStringLiteral 可直接將 enum 轉為 string 字面量
240
+ * // ✅ 結果:'debug' | 'error'
241
+ * import { ITSTypeAndStringLiteral } from 'ts-type';
242
+ * type MixedInput = ITSTypeAndStringLiteral<LogLevel> | 42 | symbol;
243
+ * type EnumAsIncludeKeys = ITSTypeAndStringLiteral<LogLevel.DEBUG | LogLevel.ERROR>;
244
+ * type Filtered = ITSExtractKeysV13<MixedInput, EnumAsIncludeKeys, PropertyKey>;
245
+ * // ✅ 可賦值:LogLevel.DEBUG, LogLevel.ERROR
246
+ * // ❌ 被過濾:'trace', 'fatal', 42, symbol
247
+ *
248
+ * // 13. 數字 enum 直接作為 IncludeKeys
249
+ * // ✅ 結果:200 | 404 | 500
250
+ * type AllCodes = 200 | 301 | 404 | 500 | 503;
251
+ * type StatusCodes = ITSExtractKeysV13<AllCodes, StatusCode, PropertyKey>;
252
+ * ```
253
+ *
254
+ * @see ITSExcludeFilterKeys
255
+ */
256
+ export type ITSExtractKeysV13<T, IncludeKeys extends PropertyKey, AllowedPropertyKey extends PropertyKey = PropertyKey> = T extends infer U ? U extends AllowedPropertyKey ? U extends IncludeKeys ? U : never : never : never;
@@ -1 +1 @@
1
- {"version":3,"file":"filter.js","sourceRoot":"","sources":["filter.ts"],"names":[],"mappings":";AAAA;;GAEG","sourcesContent":["/**\n * Created by user on 2019/6/8.\n */\n\n/**\n * 從 T 中排除可指派給 U 的類型,並替換為 R\n * Exclude from T those types that are assignable to U, and replace to R\n * \n * @example\n * type Test = string | number | boolean;\n * type Result = ITSExclude2<Test, string, never>; // number | boolean\n */\nexport type ITSExclude2<T, U, R = T> = T extends U ? never : R;\n\n/**\n * 從 T 中提取可指派給 U 的類型,並替換為 R\n * Extract from T those types that are assignable to U, and replace to R\n * \n * @example\n * type Test = string | number | boolean;\n * type Result = ITSExtract2<Test, string, 'text'>; // 'text' | number | boolean\n */\nexport type ITSExtract2<T, U, R = T> = T extends U ? R : never;\n\n/**\n * 提取 T 中屬於 U 的鍵\n * Extract keys from T that belong to U\n */\nexport type ITSExtractKeyof<T, U> = Extract<keyof T, U>;\n\n/**\n * 從類陣列類型中提取指定索引的類型\n * Extract types of specified indexes from array-like type\n * \n * @example\n * type Test = [string, number, boolean];\n * type Result = ITSExtractArrayLike<Test, 0 | 2>; // [string, boolean]\n */\nexport type ITSExtractArrayLike<A, K extends Extract<keyof A, number> = Extract<keyof A, number>> = {\n\t[Index in K]: A[Index];\n};\n\n/**\n * 取得類陣列類型的所有數字索引鍵\n * Get all numeric index keys of array-like type\n */\nexport type ITSKeyofArrayLike<A> = keyof ITSExtractArrayLike<A>;\n\n/**\n * 取得可為 null 或 undefined 的類型\n * Get types that can be null or undefined\n * \n * @example\n * type Test = string | number | null;\n * type Result = ITSNullable<Test>; // string | number | null\n */\nexport type ITSNullable<T> = T extends null | undefined ? T : never;\n\n/**\n * 找出 T 當中與 U 相同的鍵\n * Find keys that are the same between T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSKeyofSame<A, B>; // 'a'\n */\nexport type ITSKeyofSame<T, U> = Extract<keyof T, keyof U>;\n/**\n * 找出 T 當中與 U 不同的鍵\n * Find keys that are different between T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSKeyofDiff<A, B>; // 'b'\n */\nexport type ITSKeyofDiff<T, U> = Exclude<keyof T, ITSKeyofSame<T, U>>;\n\n/**\n * 找出 T 與 U 當中同時存在的鍵\n * Find keys that exist in both T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSKeyofBothSame<A, B>; // 'a'\n */\nexport type ITSKeyofBothSame<T, U> = ITSKeyofSame<T, U> | ITSKeyofSame<U, T>;\n\n/**\n * 去除 T 與 U 當中同時存在的鍵\n * Remove keys that exist in both T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSKeyofBothDiff<A, B>; // 'b' | 'c'\n */\nexport type ITSKeyofBothDiff<T, U> = ITSKeyofDiff<T, U> | ITSKeyofDiff<U, T>;\n\n\n"]}
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["filter.ts"],"names":[],"mappings":";AAAA;;GAEG","sourcesContent":["/**\n * Created by user on 2019/6/8.\n */\n\n/**\n * 從 T 中排除可指派給 U 的類型,並替換為 R\n * Exclude from T those types that are assignable to U, and replace to R\n * \n * @example\n * type Test = string | number | boolean;\n * type Result = ITSExclude2<Test, string, never>; // number | boolean\n */\nexport type ITSExclude2<T, U, R = T> = T extends U ? never : R;\n\n/**\n * 從 T 中提取可指派給 U 的類型,並替換為 R\n * Extract from T those types that are assignable to U, and replace to R\n * \n * @example\n * type Test = string | number | boolean;\n * type Result = ITSExtract2<Test, string, 'text'>; // 'text' | number | boolean\n */\nexport type ITSExtract2<T, U, R = T> = T extends U ? R : never;\n\n/**\n * 提取 T 中屬於 U 的鍵\n * Extract keys from T that belong to U\n */\nexport type ITSExtractKeyof<T, U> = Extract<keyof T, U>;\n\n/**\n * 從類陣列類型中提取指定索引的類型\n * Extract types of specified indexes from array-like type\n * \n * @example\n * type Test = [string, number, boolean];\n * type Result = ITSExtractArrayLike<Test, 0 | 2>; // [string, boolean]\n */\nexport type ITSExtractArrayLike<A, K extends Extract<keyof A, number> = Extract<keyof A, number>> = {\n\t[Index in K]: A[Index];\n};\n\n/**\n * 取得類陣列類型的所有數字索引鍵\n * Get all numeric index keys of array-like type\n */\nexport type ITSKeyofArrayLike<A> = keyof ITSExtractArrayLike<A>;\n\n/**\n * 取得可為 null 或 undefined 的類型\n * Get types that can be null or undefined\n * \n * @example\n * type Test = string | number | null;\n * type Result = ITSNullable<Test>; // string | number | null\n */\nexport type ITSNullable<T> = T extends null | undefined ? T : never;\n\n/**\n * 找出 T 當中與 U 相同的鍵\n * Find keys that are the same between T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSKeyofSame<A, B>; // 'a'\n */\nexport type ITSKeyofSame<T, U> = Extract<keyof T, keyof U>;\n/**\n * 找出 T 當中與 U 不同的鍵\n * Find keys that are different between T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSKeyofDiff<A, B>; // 'b'\n */\nexport type ITSKeyofDiff<T, U> = Exclude<keyof T, ITSKeyofSame<T, U>>;\n\n/**\n * 找出 T 與 U 當中同時存在的鍵\n * Find keys that exist in both T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSKeyofBothSame<A, B>; // 'a'\n */\nexport type ITSKeyofBothSame<T, U> = ITSKeyofSame<T, U> | ITSKeyofSame<U, T>;\n\n/**\n * 去除 T 與 U 當中同時存在的鍵\n * Remove keys that exist in both T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSKeyofBothDiff<A, B>; // 'b' | 'c'\n */\nexport type ITSKeyofBothDiff<T, U> = ITSKeyofDiff<T, U> | ITSKeyofDiff<U, T>;\n\n\n/**\n * ITSFilterKeysString - 基礎鍵過濾類型\n * 從聯合類型中排除指定的字符串鍵\n *\n * 使用範例:\n * @example\n * type AllKeys = 'log' | 'debug' | 'constructor' | 'error';\n * type PublicKeys = ITSFilterKeysString<AllKeys, 'constructor'>; // 'log' | 'debug' | 'error'\n * type SafeKeys = ITSFilterKeysString<AllKeys, 'constructor' | 'error'>; // 'log' | 'debug'\n * \n * @example\n * type ITSFilterKeysString<T, ExcludeKeys extends string = never> = T extends infer U\n * \t? U extends string\n * \t\t? U extends ExcludeKeys ? never : U\n * \t\t: never\n * \t: never;\n * \n * @see ITSExcludeFilterKeys\n */\nexport type ITSExcludeFilterKeysString<T, ExcludeKeys extends string = never> = ITSExcludeFilterKeys<T, ExcludeKeys, string>;\n\n/**\n * ITSFilterKeysPropertyKey - 支持 PropertyKey(string | number | symbol)的版本\n *\n * 使用範例:\n * @example\n * type AllKeys = 'log' | 'debug' | 'constructor' | 42 | symbol;\n * type StringKeys = ITSFilterKeysPropertyKey<AllKeys, number | symbol>; // 'log' | 'debug' | 'constructor'\n * type NoSymbol = ITSFilterKeysPropertyKey<AllKeys, symbol>; // 'log' | 'debug' | 'constructor' | 42\n * \n * @example\n * type ITSFilterKeysPropertyKey<T, ExcludeKeys extends PropertyKey = never> = T extends infer U\n * \t? U extends PropertyKey\n * \t\t? U extends ExcludeKeys ? never : U\n * \t\t: never\n * \t: never;\n * \n * @see ITSExcludeFilterKeys\n */\nexport type ITSExcludeFilterKeysPropertyKey<T, ExcludeKeys extends PropertyKey = never> = ITSExcludeFilterKeys<T, ExcludeKeys, PropertyKey>;\n\n/**\n * ITSFilterKeys - 可配置鍵類型範圍的版本\n * 第三個類型參數 `AllowedPropertyKey` 允許精確控制保留哪些類型的鍵\n *\n * 使用範例:\n * @example\n * ```\n * type AllKeys = 'log' | 'debug' | 42 | 99 | symbol;\n *\n * // 只保留 string 類型,排除 'log'\n * type StringOnly = ITSFilterKeys<AllKeys, 'log', string>; // 'debug'\n *\n * // 只保留 number 類型,不排除任何鍵\n * type NumOnly = ITSFilterKeys<AllKeys, never, number>; // 42 | 99\n *\n * // 保留 string | number,排除 'debug'\n * type Mixed = ITSFilterKeys<AllKeys, 'debug', string | number>; // 'log' | 42 | 99\n * ```\n *\n * 三代版本對比:\n * ITSFilterKeysString: 固定處理 string(最基礎)\n * ITSFilterKeysPropertyKey: 固定處理 PropertyKey(更廣泛)\n * ITSFilterKeys: 可配置 AllowedPropertyKey 參數(最靈活)\n * \n * @see ITSExtractKeysV13\n */\nexport type ITSExcludeFilterKeys<T, ExcludeKeys extends PropertyKey = never, AllowedPropertyKey extends PropertyKey = PropertyKey> = T extends infer U\n\t? U extends AllowedPropertyKey\n\t\t? U extends ExcludeKeys ? never : U\n\t\t: never\n\t: never;\n\n/**\n * ITSExtractKeysV13 - 選擇器版本(只保留匹配 IncludeKeys 的鍵)\n *\n * 與 FilterKeysV3 的邏輯差異:\n * - FilterKeysV3: `U extends ExcludeKeys ? never : U` → 排除匹配的鍵\n * - ITSExtractKeysV13: `U extends IncludeKeys ? U : never` → 只保留匹配的鍵\n *\n * 設計理念:\n * ---------------------------\n * ExtractKeyofV12 系列的核心需求是「篩選符合 V 類型的鍵」。\n * FilterKeys 系列的設計是「排除」思維( ExcludeKeys ),\n * 而 ITSExtractKeysV13 採用「選擇」思維( IncludeKeys ),更符合鍵提取的語義。\n *\n * 與 FilterKeysV3 實作的對比:\n * - FilterKeysV3: `FilterKeysV3<T, never, V>`(用 AllowedPropertyKey 篩選,ExcludeKeys 設為 never)\n * - ITSExtractKeysV13: `ITSExtractKeysV13<T, V, PropertyKey>`(直接用 IncludeKeys 篩選)\n *\n * 使用範例與測試驗證:\n * ```typescript\n * type AllKeys = 'log' | 'debug' | 'error' | 42 | 99 | symbol;\n *\n * // 1. 篩選 string 類型鍵(等同 ExtractKeyofV12d<AllKeys, string>)\n * // ✅ 結果:'log' | 'debug' | 'error'\n * type Strings = ITSExtractKeysV13<AllKeys, string, PropertyKey>;\n *\n * // 2. 篩選 number 類型鍵\n * // ✅ 結果:42 | 99\n * type Numbers = ITSExtractKeysV13<AllKeys, number, PropertyKey>;\n *\n * // 3. 只保留特定字面量\n * // ✅ 結果:'log' | 'debug'\n * type Picked = ITSExtractKeysV13<AllKeys, 'log' | 'debug', PropertyKey>;\n *\n * // 4. 特定數字字面量(只保留 42,過濾 99)\n * // ✅ 結果:42\n * // ❌ 99 會被過濾\n * type SpecificNumber = ITSExtractKeysV13<AllKeys, 42, PropertyKey>;\n *\n * // 5. 實作 ExtractKeyofV12(輸出轉為 string)\n * // ✅ 結果:'log' | 'debug' | 'error'\n * type V12_Strings = ITSExtractKeysV13<AllKeys, string, PropertyKey> & string;\n *\n * // 6. 限制輸入類型為 string(等同 FilterKeysV3<AllKeys, never, string>)\n * // ✅ 結果:'log' | 'debug' | 'error'\n * // ❌ number/symbol 被過濾\n * type StringOnly = ITSExtractKeysV13<AllKeys, PropertyKey, string>;\n *\n * // 7. symbol 類型篩選(結果為 never)\n * // ✅ 結果:never(symbol 無法通過 PropertyKey 匹配 string/number)\n * type SymbolFiltered = ITSExtractKeysV13<AllKeys, symbol, PropertyKey>;\n * ```\n *\n * Enum 類型處理範例:\n * ------------------\n * TypeScript enum 作為類型時,需使用模板字面量 `${Enum}` 或 keyof typeof 獲取成員。\n *\n * ```typescript\n * enum LogLevel {\n * DEBUG = 'debug',\n * INFO = 'info',\n * WARN = 'warn',\n * ERROR = 'error'\n * }\n *\n * enum StatusCode {\n * OK = 200,\n * NOT_FOUND = 404,\n * ERROR = 500\n * }\n *\n * // 8. 從 enum 鍵中篩選(使用 keyof typeof)\n * // ✅ 結果:'DEBUG' | 'INFO'\n * type EnumKeys = keyof typeof LogLevel; // 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'\n * type PickedEnumKeys = ITSExtractKeysV13<EnumKeys, 'DEBUG' | 'INFO', PropertyKey>;\n *\n * // 11. 數字 enum 的值篩選(使用 infer 提取數字)\n * // ✅ 結果:200 | 500\n * type StatusEnumValues = `${StatusCode}` extends `${infer N extends number}` ? N : never;\n * type PickedStatusValues = ITSExtractKeysV13<200 | 404 | 500, StatusEnumValues, PropertyKey>;\n *\n * // 12. enum 作為第二參數(IncludeKeys)使用 ITSTypeAndStringLiteral\n * // 搭配 ts-type 的 ITSTypeAndStringLiteral 可直接將 enum 轉為 string 字面量\n * // ✅ 結果:'debug' | 'error'\n * import { ITSTypeAndStringLiteral } from 'ts-type';\n * type MixedInput = ITSTypeAndStringLiteral<LogLevel> | 42 | symbol;\n * type EnumAsIncludeKeys = ITSTypeAndStringLiteral<LogLevel.DEBUG | LogLevel.ERROR>;\n * type Filtered = ITSExtractKeysV13<MixedInput, EnumAsIncludeKeys, PropertyKey>;\n * // ✅ 可賦值:LogLevel.DEBUG, LogLevel.ERROR\n * // ❌ 被過濾:'trace', 'fatal', 42, symbol\n *\n * // 13. 數字 enum 直接作為 IncludeKeys\n * // ✅ 結果:200 | 404 | 500\n * type AllCodes = 200 | 301 | 404 | 500 | 503;\n * type StatusCodes = ITSExtractKeysV13<AllCodes, StatusCode, PropertyKey>;\n * ```\n * \n * @see ITSExcludeFilterKeys\n */\nexport type ITSExtractKeysV13<T, IncludeKeys extends PropertyKey, AllowedPropertyKey extends PropertyKey = PropertyKey> = T extends infer U\n\t? U extends AllowedPropertyKey\n\t\t? U extends IncludeKeys ? U : never\n\t\t: never\n\t: never;\n\n"]}
@@ -5,7 +5,7 @@
5
5
  * 提供提取物件成員(方法)的工具類型
6
6
  * Provides utility types for extracting object members (methods)
7
7
  */
8
- import { ITSExtractRecord } from './pick-type';
8
+ import { ITSPickByType } from './pick-type';
9
9
  import { ITSPropertyKey } from '../../type/base';
10
10
  import { ITSExtractKeyof } from '../filter';
11
11
  /**
@@ -21,7 +21,7 @@ import { ITSExtractKeyof } from '../filter';
21
21
  * type Methods = ITSMemberMethods<User>;
22
22
  * // type Methods = { greet(): void; fetch(): Promise<void>; }
23
23
  */
24
- export type ITSMemberMethods<T> = ITSExtractRecord<T, Function, Extract<keyof T, ITSPropertyKey>>;
24
+ export type ITSMemberMethods<T> = ITSPickByType<T, Function, Extract<keyof T, ITSPropertyKey>>;
25
25
  /**
26
26
  * 取得物件方法的鍵
27
27
  * Get keys of object methods
@@ -36,3 +36,133 @@ export type ITSMemberMethods<T> = ITSExtractRecord<T, Function, Extract<keyof T,
36
36
  * // type MethodKeys = "greet" | "fetch"
37
37
  */
38
38
  export type ITSKeyofMemberMethods<T> = ITSExtractKeyof<ITSMemberMethods<T>, ITSPropertyKey>;
39
+ /**
40
+ * 版本 12: 完全泛化版 - 支持任意鍵值類型與自定義條件
41
+ * 可配置:1) 值類型條件 2) 鍵排除列表 3) 輸出鍵類型
42
+ *
43
+ * ✅ 跨模組驗證:使用 infer 延遲類型解析,即使跨模組引用也能正確運作,
44
+ * 避免 IMethods 變為 string 的問題
45
+ *
46
+ * @example
47
+ * ```
48
+ * type IMethods2 = "assert" | "clear" | "count" | "countReset" | "debug"
49
+ * | "dir" | "dirxml" | "error" | "group" | "groupCollapsed" | "groupEnd"
50
+ * | "info" | "log" | "table" | "time" | "timeEnd" | "timeLog" | "timeStamp"
51
+ * | "trace" | "warn" | "profile" | "profileEnd"
52
+ * export type IMethods2 = ITSExcludeFilterKeys<ITSExtractKeysV13<ITSMemberMethodsV12<Console, Function, 'constructor'>, string>, "Console" | 'new' | 'prototype' | 'Console' | 'length'>;
53
+ * ```
54
+ *
55
+ * 類型參數:
56
+ * - T: 輸入對象類型(需 extends object)
57
+ * - ValueCond: 值類型條件(預設為函數類型 `(...args: any[]) => any`)
58
+ * - ExcludeKeys: 要排除的鍵列表(預設為 never,不排除任何鍵)
59
+ *
60
+ * 與 MemberMethodsV11 的差異:
61
+ * - V11: 固定排除函數類型的鍵,只能排除單個鍵
62
+ * - V12: 可自定義值類型條件(如只提取返回 Promise 的方法),支持排除多個鍵
63
+ *
64
+ * 核心機制:
65
+ * ---------------------------
66
+ * 1. 使用 `T extends infer U` 捕獲輸入類型,實現跨模組延遲解析
67
+ * 2. 映射類型遍歷所有鍵,篩選符合 ValueCond 的鍵
68
+ * 3. 若 ExcludeKeys 不為 never,使用 `as` 重映射排除指定鍵
69
+ *
70
+ * ✅ 跨模組驗證:使用 infer 延遲類型解析,即使跨模組引用也能正確運作,
71
+ * 避免 IMethods 變為 string 的問題
72
+ *
73
+ * 使用範例:
74
+ * ---------------------------
75
+ * @example
76
+ * ```typescript
77
+ * interface MyClass {
78
+ * name: string;
79
+ * log(): void;
80
+ * debug(): void;
81
+ * error(): void;
82
+ * constructor(): void;
83
+ * _privateMethod(): void;
84
+ * }
85
+ *
86
+ * // 1. 提取所有方法(預設行為,等同 MemberMethodsV11 無排除時)
87
+ * // ✅ 結果:'log' | 'debug' | 'error' | 'constructor' | '_privateMethod'
88
+ * type AllMethods = MemberMethodsV12<MyClass>;
89
+ *
90
+ * // 2. 提取方法但排除 constructor
91
+ * // ✅ 結果:'log' | 'debug' | 'error' | '_privateMethod'
92
+ * // ❌ 'constructor' 被排除
93
+ * type NoCtor = MemberMethodsV12<MyClass, (...args: any[]) => any, 'constructor'>;
94
+ *
95
+ * // 3. 排除多個鍵
96
+ * // ✅ 結果:'log' | 'debug' | 'error'
97
+ * // ❌ 'constructor'、'_privateMethod' 被排除
98
+ * type PublicMethods = MemberMethodsV12<MyClass, (...args: any[]) => any, 'constructor' | '_privateMethod'>;
99
+ *
100
+ * // 4. 自定義值類型條件 - 只提取返回 string 的方法
101
+ * interface StringReturnClass {
102
+ * getName(): string;
103
+ * getId(): number;
104
+ * log(): void;
105
+ * }
106
+ * // ✅ 結果:'getName'
107
+ * type StringMethods = MemberMethodsV12<StringReturnClass, () => string>;
108
+ *
109
+ * // 5. 自定義值類型 - 只提取返回 Promise 的方法
110
+ * interface AsyncClass {
111
+ * fetchData(): Promise<string>;
112
+ * syncMethod(): string;
113
+ * save(): Promise<void>;
114
+ * }
115
+ * // ✅ 結果:'fetchData' | 'save'
116
+ * type AsyncMethods = MemberMethodsV12<AsyncClass, () => Promise<any>>;
117
+ *
118
+ * // 6. 泛型類別中使用
119
+ * class GenericService<T> {
120
+ * data: T;
121
+ * fetch(): Promise<T>;
122
+ * save(): Promise<void>;
123
+ * private internal(): void;
124
+ * }
125
+ * // ✅ 結果:'fetch' | 'save' | 'internal'(含私有方法)
126
+ * // ❌ 'data' 被過濾(不是函數)
127
+ * type ServiceMethods = MemberMethodsV12<GenericService<any>>;
128
+ * // ✅ 結果:'fetch' | 'save'
129
+ * // ❌ 'internal' 也被排除(假設要排除私有方法)
130
+ * type PublicServiceMethods = MemberMethodsV12<GenericService<any>, (...args: any[]) => any, 'internal'>;
131
+ *
132
+ * // 7. 與 ExtractKeyofV12 組合使用 - 提取並轉換為 string 類型
133
+ * type MyClassMethods = MemberMethodsV12<MyClass>;
134
+ * type StringMethodKeys = ExtractKeyofV12<MyClassMethods, string>; // 'log' | 'debug' | 'error' | ...
135
+ *
136
+ * // 8. 內化排除模式 - 最簡潔用法
137
+ * // 將所有排除邏輯集中在 MemberMethodsV12 的 ExcludeKeys 參數中
138
+ * type CleanMethods = MemberMethodsV12<
139
+ * MyClass,
140
+ * Function,
141
+ * 'constructor' | 'new' | 'prototype' | '_privateMethod'
142
+ * >;
143
+ * ```
144
+ *
145
+ * 進階組合範例:
146
+ * ---------------------------
147
+ * @example
148
+ * ```typescript
149
+ * // 組合 FilterKeys 實現分階段過濾
150
+ * type Stage1 = MemberMethodsV12<ApiA>; // 提取 A 的方法
151
+ * type Stage2 = MemberMethodsV12<ApiB>; // 提取 B 的方法
152
+ * type Combined = FilterKeys<Stage1 | Stage2, 'constructor' | 'init'>;
153
+ *
154
+ * // 條件化排除
155
+ * type ConditionalMethods<T, ExcludePrivate extends boolean> =
156
+ * ExcludePrivate extends true
157
+ * ? MemberMethodsV12<T, (...args: any[]) => any, `_${string}`>
158
+ * : MemberMethodsV12<T>;
159
+ * ```
160
+ *
161
+ * @see ITSExcludeFilterKeys
162
+ * @see ITSExtractKeysV13
163
+ */
164
+ export type ITSMemberMethodsV12<T, ValueCond = (...args: any[]) => any, ExcludeKeys extends PropertyKey = never> = T extends infer U ? U extends object ? ExcludeKeys extends never ? {
165
+ [K in keyof U]: U[K] extends ValueCond ? K : never;
166
+ }[keyof U] : {
167
+ [K in keyof U as U[K] extends ValueCond ? K extends ExcludeKeys ? never : K : never]: any;
168
+ } extends infer M ? keyof M : never : never : never;
@@ -1 +1 @@
1
- {"version":3,"file":"member.js","sourceRoot":"","sources":["member.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG","sourcesContent":["/**\n * 記錄成員工具\n * Record Member Utilities\n * \n * 提供提取物件成員(方法)的工具類型\n * Provides utility types for extracting object members (methods)\n */\n\nimport { ITSExtractRecord } from './pick-type';\nimport { ITSPropertyKey } from '../../type/base';\nimport { ITSExtractKeyof } from '../filter';\n\n/**\n * 過濾出所有成員是函數且鍵類型為字串或符號的屬性\n * Filter out all members that are functions and key types are string or symbol\n * \n * @example\n * class User {\n * name: string;\n * greet(): void;\n * async fetch(): Promise<void>;\n * }\n * type Methods = ITSMemberMethods<User>;\n * // type Methods = { greet(): void; fetch(): Promise<void>; }\n */\nexport type ITSMemberMethods<T> = ITSExtractRecord<T, Function, Extract<keyof T, ITSPropertyKey>>;\n\n/**\n * 取得物件方法的鍵\n * Get keys of object methods\n * \n * @example\n * class User {\n * name: string;\n * greet(): void;\n * async fetch(): Promise<void>;\n * }\n * type MethodKeys = ITSKeyofMemberMethods<User>;\n * // type MethodKeys = \"greet\" | \"fetch\"\n */\nexport type ITSKeyofMemberMethods<T> = ITSExtractKeyof<ITSMemberMethods<T>, ITSPropertyKey>;\n"]}
1
+ {"version":3,"file":"member.js","sourceRoot":"","sources":["member.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG","sourcesContent":["/**\n * 記錄成員工具\n * Record Member Utilities\n * \n * 提供提取物件成員(方法)的工具類型\n * Provides utility types for extracting object members (methods)\n */\n\nimport { ITSExtractRecord, ITSPickByType } from './pick-type';\nimport { ITSPropertyKey } from '../../type/base';\nimport { ITSExtractKeyof } from '../filter';\n\n/**\n * 過濾出所有成員是函數且鍵類型為字串或符號的屬性\n * Filter out all members that are functions and key types are string or symbol\n * \n * @example\n * class User {\n * name: string;\n * greet(): void;\n * async fetch(): Promise<void>;\n * }\n * type Methods = ITSMemberMethods<User>;\n * // type Methods = { greet(): void; fetch(): Promise<void>; }\n */\nexport type ITSMemberMethods<T> = ITSPickByType<T, Function, Extract<keyof T, ITSPropertyKey>>;\n\n/**\n * 取得物件方法的鍵\n * Get keys of object methods\n * \n * @example\n * class User {\n * name: string;\n * greet(): void;\n * async fetch(): Promise<void>;\n * }\n * type MethodKeys = ITSKeyofMemberMethods<User>;\n * // type MethodKeys = \"greet\" | \"fetch\"\n */\nexport type ITSKeyofMemberMethods<T> = ITSExtractKeyof<ITSMemberMethods<T>, ITSPropertyKey>;\n\n/**\n * 版本 12: 完全泛化版 - 支持任意鍵值類型與自定義條件\n * 可配置:1) 值類型條件 2) 鍵排除列表 3) 輸出鍵類型\n *\n * ✅ 跨模組驗證:使用 infer 延遲類型解析,即使跨模組引用也能正確運作,\n * 避免 IMethods 變為 string 的問題\n * \n * @example\n * ```\n * type IMethods2 = \"assert\" | \"clear\" | \"count\" | \"countReset\" | \"debug\"\n * | \"dir\" | \"dirxml\" | \"error\" | \"group\" | \"groupCollapsed\" | \"groupEnd\"\n * | \"info\" | \"log\" | \"table\" | \"time\" | \"timeEnd\" | \"timeLog\" | \"timeStamp\"\n * | \"trace\" | \"warn\" | \"profile\" | \"profileEnd\"\n * export type IMethods2 = ITSExcludeFilterKeys<ITSExtractKeysV13<ITSMemberMethodsV12<Console, Function, 'constructor'>, string>, \"Console\" | 'new' | 'prototype' | 'Console' | 'length'>;\n * ```\n *\n * 類型參數:\n * - T: 輸入對象類型(需 extends object)\n * - ValueCond: 值類型條件(預設為函數類型 `(...args: any[]) => any`)\n * - ExcludeKeys: 要排除的鍵列表(預設為 never,不排除任何鍵)\n *\n * 與 MemberMethodsV11 的差異:\n * - V11: 固定排除函數類型的鍵,只能排除單個鍵\n * - V12: 可自定義值類型條件(如只提取返回 Promise 的方法),支持排除多個鍵\n *\n * 核心機制:\n * ---------------------------\n * 1. 使用 `T extends infer U` 捕獲輸入類型,實現跨模組延遲解析\n * 2. 映射類型遍歷所有鍵,篩選符合 ValueCond 的鍵\n * 3. 若 ExcludeKeys 不為 never,使用 `as` 重映射排除指定鍵\n *\n * ✅ 跨模組驗證:使用 infer 延遲類型解析,即使跨模組引用也能正確運作,\n * 避免 IMethods 變為 string 的問題\n *\n * 使用範例:\n * ---------------------------\n * @example\n * ```typescript\n * interface MyClass {\n * name: string;\n * log(): void;\n * debug(): void;\n * error(): void;\n * constructor(): void;\n * _privateMethod(): void;\n * }\n *\n * // 1. 提取所有方法(預設行為,等同 MemberMethodsV11 無排除時)\n * // ✅ 結果:'log' | 'debug' | 'error' | 'constructor' | '_privateMethod'\n * type AllMethods = MemberMethodsV12<MyClass>;\n *\n * // 2. 提取方法但排除 constructor\n * // ✅ 結果:'log' | 'debug' | 'error' | '_privateMethod'\n * // ❌ 'constructor' 被排除\n * type NoCtor = MemberMethodsV12<MyClass, (...args: any[]) => any, 'constructor'>;\n *\n * // 3. 排除多個鍵\n * // ✅ 結果:'log' | 'debug' | 'error'\n * // ❌ 'constructor'、'_privateMethod' 被排除\n * type PublicMethods = MemberMethodsV12<MyClass, (...args: any[]) => any, 'constructor' | '_privateMethod'>;\n *\n * // 4. 自定義值類型條件 - 只提取返回 string 的方法\n * interface StringReturnClass {\n * getName(): string;\n * getId(): number;\n * log(): void;\n * }\n * // ✅ 結果:'getName'\n * type StringMethods = MemberMethodsV12<StringReturnClass, () => string>;\n *\n * // 5. 自定義值類型 - 只提取返回 Promise 的方法\n * interface AsyncClass {\n * fetchData(): Promise<string>;\n * syncMethod(): string;\n * save(): Promise<void>;\n * }\n * // ✅ 結果:'fetchData' | 'save'\n * type AsyncMethods = MemberMethodsV12<AsyncClass, () => Promise<any>>;\n *\n * // 6. 泛型類別中使用\n * class GenericService<T> {\n * data: T;\n * fetch(): Promise<T>;\n * save(): Promise<void>;\n * private internal(): void;\n * }\n * // ✅ 結果:'fetch' | 'save' | 'internal'(含私有方法)\n * // ❌ 'data' 被過濾(不是函數)\n * type ServiceMethods = MemberMethodsV12<GenericService<any>>;\n * // ✅ 結果:'fetch' | 'save'\n * // ❌ 'internal' 也被排除(假設要排除私有方法)\n * type PublicServiceMethods = MemberMethodsV12<GenericService<any>, (...args: any[]) => any, 'internal'>;\n *\n * // 7. 與 ExtractKeyofV12 組合使用 - 提取並轉換為 string 類型\n * type MyClassMethods = MemberMethodsV12<MyClass>;\n * type StringMethodKeys = ExtractKeyofV12<MyClassMethods, string>; // 'log' | 'debug' | 'error' | ...\n *\n * // 8. 內化排除模式 - 最簡潔用法\n * // 將所有排除邏輯集中在 MemberMethodsV12 的 ExcludeKeys 參數中\n * type CleanMethods = MemberMethodsV12<\n * MyClass,\n * Function,\n * 'constructor' | 'new' | 'prototype' | '_privateMethod'\n * >;\n * ```\n *\n * 進階組合範例:\n * ---------------------------\n * @example\n * ```typescript\n * // 組合 FilterKeys 實現分階段過濾\n * type Stage1 = MemberMethodsV12<ApiA>; // 提取 A 的方法\n * type Stage2 = MemberMethodsV12<ApiB>; // 提取 B 的方法\n * type Combined = FilterKeys<Stage1 | Stage2, 'constructor' | 'init'>;\n *\n * // 條件化排除\n * type ConditionalMethods<T, ExcludePrivate extends boolean> =\n * ExcludePrivate extends true\n * ? MemberMethodsV12<T, (...args: any[]) => any, `_${string}`>\n * : MemberMethodsV12<T>;\n * ```\n * \n * @see ITSExcludeFilterKeys\n * @see ITSExtractKeysV13\n */\nexport type ITSMemberMethodsV12<\n\tT,\n\tValueCond = (...args: any[]) => any,\n\tExcludeKeys extends PropertyKey = never\n>\t// 1. T extends infer U - 使用 infer 捕獲輸入類型,實現延遲解析\n\t= T extends infer U\n\t// 2. U extends object - 確保輸入是對象類型(可遍歷鍵)\n\t? U extends object\n\t\t// 3. ExcludeKeys extends never - 檢查是否需要排除特定鍵\n\t\t? ExcludeKeys extends never\n\t\t\t// 3a. 無需排除 - 使用基本映射類型遍歷所有鍵\n\t\t\t// 遍歷 U 的所有鍵 K,若值類型 U[K] 符合 ValueCond 則保留 K,否則設為 never\n\t\t\t? { [K in keyof U]: U[K] extends ValueCond ? K : never; }[keyof U]\n\t\t\t// 3b. 需要排除 - 使用「as」重映射語法進行鍵過濾\n\t\t\t// 邏輯:先檢查值類型是否符合 ValueCond,再檢查鍵是否在 ExcludeKeys 中\n\t\t\t: { [K in keyof U as U[K] extends ValueCond\n\t\t\t\t// 若值符合條件,進一步檢查鍵是否需要排除\n\t\t\t\t? K extends ExcludeKeys ? never : K // 在排除列表中則設為 never,否則保留 K\n\t\t\t\t// 若值不符合條件,設為 never(過濾掉)\n\t\t\t\t: never]: any } extends infer M ? keyof M : never\n\t\t// U 不是 object,返回 never(無法提取方法)\n\t\t: never\n\t// T 無法解析為 infer U,返回 never\n\t: never;\n"]}
@@ -60,6 +60,20 @@ export type ITSValueOrArrayMaybeReadonly<T> = T | ITSArrayListMaybeReadonly<T>;
60
60
  * // type PropKey = string | symbol
61
61
  */
62
62
  export type ITSPropertyKey = string | symbol;
63
+ /**
64
+ * 屬性鍵或索引類型:字串、符號或數字
65
+ * Property key or index type: string, symbol, or number
66
+ *
67
+ * 適用於物件屬性存取與陣列索引的聯合類型
68
+ * Suitable for union type covering object property access and array index access
69
+ *
70
+ * @see {@link ITSPropertyKey} - 僅字串或符號(不含數字索引)
71
+ *
72
+ * @example
73
+ * type KeyOrIdx = ITSPropertyKeyOrIndex;
74
+ * // type KeyOrIdx = string | symbol | number
75
+ */
76
+ export type ITSPropertyKeyOrIndex = ITSPropertyKey | number;
63
77
  /**
64
78
  * 任意函數類型
65
79
  * Any function type
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["base.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG","sourcesContent":["/**\n * 基礎類型定義\n * Base Type Definitions\n * \n * 提供常用的基礎類型別名和工具類型\n * Provides commonly used base type aliases and utility types\n */\n\nimport { ITSTypeFunction } from '../generic';\n\n/**\n * 陣列類型:可讀寫陣列或唯讀陣列\n * Array type: writable array or readonly array\n * \n * @example\n * type StringList = ITSArrayListMaybeReadonly<string>;\n * // type StringList = string[] | readonly string[]\n */\nexport type ITSArrayListMaybeReadonly<T> = T[] | readonly T[];\n\n/**\n * 鍵的類型:符號、字串或數字\n * Key types: symbol, string, or number\n * \n * @example\n * type Keys = ITSKeys;\n * // type Keys = symbol | string | number\n */\nexport type ITSKeys = symbol | string | number;\n\n/**\n * 建構函數類型\n * Constructor type\n * \n * @example\n * type MyConstructor = ITSConstructorLike<MyClass>;\n * // type MyConstructor = new (...args: any) => MyClass\n */\nexport type ITSConstructorLike<T extends any = any> = new(...args: any) => T;\n\n/**\n * 值或陣列:單一值或其陣列\n * Value or array: single value or array of that value\n * \n * @example\n * type StringOrArray = ITSValueOrArray<string>;\n * // type StringOrArray = string | string[]\n */\nexport type ITSValueOrArray<T> = T | T[];\n\n/**\n * 值或可能唯讀的陣列:單一值、可讀寫陣列或唯讀陣列\n * Value or possibly readonly array: single value, writable array, or readonly array\n * \n * @example\n * type StringOrList = ITSValueOrArrayMaybeReadonly<string>;\n * // type StringOrList = string | string[] | readonly string[]\n */\nexport type ITSValueOrArrayMaybeReadonly<T> = T | ITSArrayListMaybeReadonly<T>;\n\n/**\n * 屬性鍵類型:字串或符號\n * Property key type: string or symbol\n * \n * @example\n * type PropKey = ITSPropertyKey;\n * // type PropKey = string | symbol\n */\nexport type ITSPropertyKey = string | symbol;\n\n/**\n * 任意函數類型\n * Any function type\n * \n * @example\n * type AnyFunc = ITSAnyFunction;\n * // type AnyFunc = (...args: any[]) => any\n */\nexport type ITSAnyFunction = ITSTypeFunction<any>;\n\n/**\n * 基本原始類型:數字、字串或布林值\n * Basic primitive types: number, string, or boolean\n * \n * @example\n * type Primitive = ITSBasicPrimitive;\n * // type Primitive = number | string | boolean\n */\nexport type ITSBasicPrimitive = number | string | boolean;\n\n/**\n * 可為空的原始類型:null 或 undefined\n * Nullable primitive types: null or undefined\n * \n * @example\n * type Nullish = ITSNullPrimitive;\n * // type Nullish = null | undefined\n */\nexport type ITSNullPrimitive = null | undefined;\n"]}
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["base.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG","sourcesContent":["/**\n * 基礎類型定義\n * Base Type Definitions\n * \n * 提供常用的基礎類型別名和工具類型\n * Provides commonly used base type aliases and utility types\n */\n\nimport { ITSTypeFunction } from '../generic';\n\n/**\n * 陣列類型:可讀寫陣列或唯讀陣列\n * Array type: writable array or readonly array\n * \n * @example\n * type StringList = ITSArrayListMaybeReadonly<string>;\n * // type StringList = string[] | readonly string[]\n */\nexport type ITSArrayListMaybeReadonly<T> = T[] | readonly T[];\n\n/**\n * 鍵的類型:符號、字串或數字\n * Key types: symbol, string, or number\n * \n * @example\n * type Keys = ITSKeys;\n * // type Keys = symbol | string | number\n */\nexport type ITSKeys = symbol | string | number;\n\n/**\n * 建構函數類型\n * Constructor type\n * \n * @example\n * type MyConstructor = ITSConstructorLike<MyClass>;\n * // type MyConstructor = new (...args: any) => MyClass\n */\nexport type ITSConstructorLike<T extends any = any> = new(...args: any) => T;\n\n/**\n * 值或陣列:單一值或其陣列\n * Value or array: single value or array of that value\n * \n * @example\n * type StringOrArray = ITSValueOrArray<string>;\n * // type StringOrArray = string | string[]\n */\nexport type ITSValueOrArray<T> = T | T[];\n\n/**\n * 值或可能唯讀的陣列:單一值、可讀寫陣列或唯讀陣列\n * Value or possibly readonly array: single value, writable array, or readonly array\n * \n * @example\n * type StringOrList = ITSValueOrArrayMaybeReadonly<string>;\n * // type StringOrList = string | string[] | readonly string[]\n */\nexport type ITSValueOrArrayMaybeReadonly<T> = T | ITSArrayListMaybeReadonly<T>;\n\n/**\n * 屬性鍵類型:字串或符號\n * Property key type: string or symbol\n * \n * @example\n * type PropKey = ITSPropertyKey;\n * // type PropKey = string | symbol\n */\nexport type ITSPropertyKey = string | symbol;\n\n/**\n * 屬性鍵或索引類型:字串、符號或數字\n * Property key or index type: string, symbol, or number\n *\n * 適用於物件屬性存取與陣列索引的聯合類型\n * Suitable for union type covering object property access and array index access\n *\n * @see {@link ITSPropertyKey} - 僅字串或符號(不含數字索引)\n *\n * @example\n * type KeyOrIdx = ITSPropertyKeyOrIndex;\n * // type KeyOrIdx = string | symbol | number\n */\nexport type ITSPropertyKeyOrIndex = ITSPropertyKey | number;\n\n/**\n * 任意函數類型\n * Any function type\n * \n * @example\n * type AnyFunc = ITSAnyFunction;\n * // type AnyFunc = (...args: any[]) => any\n */\nexport type ITSAnyFunction = ITSTypeFunction<any>;\n\n/**\n * 基本原始類型:數字、字串或布林值\n * Basic primitive types: number, string, or boolean\n * \n * @example\n * type Primitive = ITSBasicPrimitive;\n * // type Primitive = number | string | boolean\n */\nexport type ITSBasicPrimitive = number | string | boolean;\n\n/**\n * 可為空的原始類型:null 或 undefined\n * Nullable primitive types: null or undefined\n * \n * @example\n * type Nullish = ITSNullPrimitive;\n * // type Nullish = null | undefined\n */\nexport type ITSNullPrimitive = null | undefined;\n"]}
@@ -159,6 +159,24 @@ export type ITSPickExtra<T, RK extends keyof T, PK extends Exclude<keyof T, RK>
159
159
  * // type Result = { name?: string; } & { age: number; email: string; }
160
160
  */
161
161
  export type ITSPickExtra2<T, PK extends keyof T, RK extends Exclude<keyof T, PK> = Exclude<keyof T, PK>> = ITSRequiredPick<T, RK> & ITSPartialPick<T, PK>;
162
+ /**
163
+ * 保留指定鍵不變(維持原本的必選/可選/唯讀屬性),其他鍵變為可選
164
+ * Keep specified keys unchanged (preserving required/optional/readonly modifiers), other keys become Partial
165
+ *
166
+ * 與 ITSPickExtra 的差異:ITSPickExtra 會將指定鍵強制設為必填,而此類型保留原始修飾符
167
+ * Difference from ITSPickExtra: ITSPickExtra forces specified keys to Required, while this type preserves original modifiers
168
+ *
169
+ * @see {@link ITSPickExtra} - 將指定鍵設為必填,其他鍵可選
170
+ * @see {@link ITSPartialWith} - 將指定鍵設為可選,其他鍵不變
171
+ *
172
+ * @example
173
+ * interface User { name: string; readonly id: string; age?: number; email: string; }
174
+ * type Result = ITSPickAndPartialOther<User, 'name' | 'id'>;
175
+ * // 輸出結果 / Output:
176
+ * // { name: string; readonly id: string; } & { age?: number; email?: string; }
177
+ * // 注意:name 維持必選,id 維持唯讀且必選,age 和 email 變為可選
178
+ */
179
+ export type ITSPickAndPartialOther<T, RK extends keyof T, PK extends Exclude<keyof T, RK> = Exclude<keyof T, RK>> = Pick<T, RK> & ITSPartialPick<T, PK>;
162
180
  /**
163
181
  * 保留指定鍵為必填,其他鍵不變
164
182
  * Keep specified keys as Required, other keys unchanged
@@ -1 +1 @@
1
- {"version":3,"file":"record.js","sourceRoot":"","sources":["record.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG","sourcesContent":["/**\n * 記錄(Record)類型操作工具\n * Record Type Manipulation Utilities\n * \n * 提供物件類型選擇、覆寫、合併等操作\n * Provides object type selection, overwrite, merge and other operations\n * \n * Created by user on 2019/6/11.\n */\n\nimport type { ITSKeyofBothDiff, ITSKeyofBothSame, ITSKeyofDiff, ITSKeyofSame } from '../helper/filter';\n\nexport type { ITSRequireRecord, ITSPartialRecord } from '../type/record/partial';\n\n/**\n * 取得兩個鍵集合的差異(已棄用)\n * Get the difference between two key sets (deprecated)\n * \n * @deprecated 請使用 ITSKeyofDiff 取代 / Please use ITSKeyofDiff instead\n */\nexport type ITSDiff<T extends keyof any, U extends keyof any> = (\n\t{ [P in T]: P }\n\t&\n\t{ [P in U]: never }\n\t&\n\t{ [x: string]: never }\n\t)[T];\n\n/**\n * 選擇 T 中與 U 相同的鍵\n * Pick keys from T that are the same as U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSPickSame<A, B>;\n * // type Result = { a: 1 }\n */\nexport type ITSPickSame<T, U> = Pick<T, ITSKeyofSame<T, U>>;\n\n/**\n * 選擇 T 中與 U 不同的鍵\n * Pick keys from T that are different from U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSPickDiff<A, B>;\n * // type Result = { b: 2 }\n */\nexport type ITSPickDiff<T, U> = Pick<T, ITSKeyofDiff<T, U>>;\n\n/**\n * 選擇 T 與 U 中同時存在的鍵\n * Pick keys that exist in both T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSPickBothSame<A, B>;\n * // type Result = { a: 1 }\n */\nexport type ITSPickBothSame<T, U> = Pick<T & U, ITSKeyofBothSame<T, U>>;\n\n/**\n * 選擇 T 與 U 中不同時存在的鍵\n * Pick keys that do not exist in both T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSPickBothDiff<A, B>;\n * // type Result = { b: 2; c: 4 }\n */\nexport type ITSPickBothDiff<T, U> = Pick<T & U, ITSKeyofBothDiff<T, U>>;\n\n/**\n * 選擇指定鍵集合 K(必須是 T 與 U 中同時存在的鍵)\n * Pick a specified key set K (must be keys that exist in both T and U)\n */\nexport type ITSPickBoth<T, U, K extends ITSKeyofBothSame<T, U> = ITSKeyofBothSame<T, U>> = Pick<T & U, K>;\n\n/**\n * 取得物件成員的類型\n * Get the type of an object member\n * \n * @see https://stackoverflow.com/questions/49198713/override-the-properties-of-an-interface-in-typescript\n */\nexport type ITSPickMember<T, K extends keyof T> = T[K];\n\n/**\n * 排除指定鍵(已棄用)\n * Exclude specified keys (deprecated)\n * \n * @deprecated 請使用 Omit 取代 / Please use Omit instead\n */\nexport type ITSPickNot<T, K extends keyof T> = Omit<T, K>;\n\n/**\n * 覆寫物件類型的屬性\n * Overwrite properties of an object type\n * \n * 用 U 中的屬性覆寫 T 中的同名屬性\n * Overwrites properties in T with the same name from U\n * \n * @see https://stackoverflow.com/questions/49198713/override-the-properties-of-an-interface-in-typescript\n * \n * @example\n * interface A1 { s: string }\n * type A2 = ITSOverwrite<A1, { s: number }>;\n * // type A2 = { s: number }\n */\nexport type ITSOverwrite<T, U> = Omit<T, keyof U> & U;\n\n/**\n * 合併兩個物件類型,處理衝突屬性\n * Merge two object types, handling conflicting properties\n * \n * 對於 T 與 U 中同時存在的鍵,取兩者的聯集類型\n * For keys that exist in both T and U, takes the union type of both\n * \n * @example\n * type Test1 = { id: number, code: string }\n * type Test2 = { id: string, code: number }\n * type Test3 = ITSMergeBoth<Test1, Test2>\n * // type Test3 = { id: string | number; code: string | number }\n * @see https://github.com/microsoft/TypeScript/issues/35627\n */\nexport type ITSMergeBoth<T, U> = ITSPickBothDiff<T, U> & Pick<T | U, ITSKeyofBothSame<T, U>>;\n\n/**\n * 選擇指定鍵並設為必填\n * Pick specified keys and mark as Required\n * \n * @example\n * interface User { name?: string; age?: number; email?: string; }\n * type RequiredName = ITSRequiredPick<User, 'name'>;\n * // type RequiredName = { name: string; age?: number; email?: string; }\n */\nexport type ITSRequiredPick<T, K extends keyof T = keyof T> = {\n\t[P in K]-?: T[P];\n};\n\n/**\n * 選擇指定鍵並設為可選\n * Pick specified keys and mark as Partial\n * \n * @example\n * interface User { name: string; age: number; email: string; }\n * type PartialName = ITSPartialPick<User, 'name'>;\n * // type PartialName = { name?: string; age: number; email: string; }\n */\nexport type ITSPartialPick<T, K extends keyof T = keyof T> = {\n\t[P in K]?: T[P];\n};\n\n/**\n * 複製類型並將指定鍵RK設為必填,其他鍵Pk設為可選\n * Clone a type and mark specified keys as Required, other keys as Partial\n * \n * @example\n * interface User { name: string; age: number; email: string; }\n * type Result = ITSPickExtra<User, 'name', 'email'>;\n * // type Result = { name: string; } & { age?: number; email?: string; }\n */\nexport type ITSPickExtra<T, RK extends keyof T, PK extends Exclude<keyof T, RK> = Exclude<keyof T, RK>> =\n\tITSRequiredPick<T, RK>\n\t& ITSPartialPick<T, PK>;\n\n/**\n * 複製類型並將指定鍵Pk設為可選,其他鍵Rk設為必填(與 ITSPickExtra 相反)\n * Clone a type and mark specified keys as Partial, other keys as Required (opposite of ITSPickExtra)\n * \n * @example\n * interface User { name: string; age: number; email: string; }\n * type Result = ITSPickExtra2<User, 'name', 'email'>;\n * // type Result = { name?: string; } & { age: number; email: string; }\n */\nexport type ITSPickExtra2<T, PK extends keyof T, RK extends Exclude<keyof T, PK> = Exclude<keyof T, PK>> =\n\tITSRequiredPick<T, RK>\n\t& ITSPartialPick<T, PK>;\n\n/**\n * 保留指定鍵為必填,其他鍵不變\n * Keep specified keys as Required, other keys unchanged\n * \n * @example\n * interface User { name: string; age: number; email: string; }\n * type Result = ITSRequiredWith<User, 'name'>;\n * // type Result = { name: string; age: number; email: string; }\n */\nexport type ITSRequiredWith<T, K extends keyof T> = Omit<T, K> & ITSRequiredPick<T, K>;\n\n/**\n * 保留指定鍵為可選,其他鍵不變\n * Keep specified keys as Partial, other keys unchanged\n * \n * @example\n * interface User { name: string; age: number; email: string; }\n * type Result = ITSPartialWith<User, 'name'>;\n * // type Result = { name?: string; age: number; email: string; }\n */\nexport type ITSPartialWith<T, K extends keyof T> = Omit<T, K> & ITSPartialPick<T, K>;\n\n/**\n * 確保物件至少具有指定的鍵集合中的一個\n * Ensure the object has at least one of the specified key sets\n * \n * @see https://stackoverflow.com/questions/40510611/typescript-interface-require-one-of-two-properties-to-exist\n * \n * @example\n * interface User { name?: string; age?: number; }\n * type AtLeastOne = ITSRequireAtLeastOne<User, 'name' | 'age'>;\n * // 需要至少提供 name 或 age 其中一個\n */\nexport type ITSRequireAtLeastOne<T, Keys extends keyof T = keyof T> =\n\tOmit<T, Keys>\n\t& {\n\t[K in Keys]-?: ITSRequiredPick<T, K>\n\t& ITSPartialPick<T, Exclude<Keys, K>>\n}[Keys];\n\n/**\n * 確保物件只能具有指定的鍵集合中的其中一個(互斥)\n * Ensure the object can only have exactly one of the specified key sets (mutually exclusive)\n *\n * @see https://stackoverflow.com/questions/40510611/typescript-interface-require-one-of-two-properties-to-exist\n * @see {@link ITSPickOne} 另一種實現方式,使用 `void` 作為其餘鍵的類型\n *\n * @example\n * interface User { name?: string; age?: number; }\n * type OnlyOne1 = ITSRequireOnlyOne<User, 'name' | 'age'>;\n * // 輸出結果:\n * // type OnlyOne1 = { name: string; age?: never; } | { age: number; name?: never; }\n * // 只能提供 name 或 age 其中一個,不能同時提供\n */\nexport type ITSRequireOnlyOne<T, Keys extends keyof T = keyof T> =\n\tOmit<T, Keys>\n\t& {\n\t[K in Keys]-?: ITSRequiredPick<T, K>\n\t& Partial<Record<Exclude<Keys, K>, never>>\n}[Keys];\n"]}
1
+ {"version":3,"file":"record.js","sourceRoot":"","sources":["record.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG","sourcesContent":["/**\n * 記錄(Record)類型操作工具\n * Record Type Manipulation Utilities\n * \n * 提供物件類型選擇、覆寫、合併等操作\n * Provides object type selection, overwrite, merge and other operations\n * \n * Created by user on 2019/6/11.\n */\n\nimport type { ITSKeyofBothDiff, ITSKeyofBothSame, ITSKeyofDiff, ITSKeyofSame } from '../helper/filter';\n\nexport type { ITSRequireRecord, ITSPartialRecord } from '../type/record/partial';\n\n/**\n * 取得兩個鍵集合的差異(已棄用)\n * Get the difference between two key sets (deprecated)\n * \n * @deprecated 請使用 ITSKeyofDiff 取代 / Please use ITSKeyofDiff instead\n */\nexport type ITSDiff<T extends keyof any, U extends keyof any> = (\n\t{ [P in T]: P }\n\t&\n\t{ [P in U]: never }\n\t&\n\t{ [x: string]: never }\n\t)[T];\n\n/**\n * 選擇 T 中與 U 相同的鍵\n * Pick keys from T that are the same as U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSPickSame<A, B>;\n * // type Result = { a: 1 }\n */\nexport type ITSPickSame<T, U> = Pick<T, ITSKeyofSame<T, U>>;\n\n/**\n * 選擇 T 中與 U 不同的鍵\n * Pick keys from T that are different from U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSPickDiff<A, B>;\n * // type Result = { b: 2 }\n */\nexport type ITSPickDiff<T, U> = Pick<T, ITSKeyofDiff<T, U>>;\n\n/**\n * 選擇 T 與 U 中同時存在的鍵\n * Pick keys that exist in both T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSPickBothSame<A, B>;\n * // type Result = { a: 1 }\n */\nexport type ITSPickBothSame<T, U> = Pick<T & U, ITSKeyofBothSame<T, U>>;\n\n/**\n * 選擇 T 與 U 中不同時存在的鍵\n * Pick keys that do not exist in both T and U\n * \n * @example\n * type A = { a: 1; b: 2; };\n * type B = { a: 3; c: 4; };\n * type Result = ITSPickBothDiff<A, B>;\n * // type Result = { b: 2; c: 4 }\n */\nexport type ITSPickBothDiff<T, U> = Pick<T & U, ITSKeyofBothDiff<T, U>>;\n\n/**\n * 選擇指定鍵集合 K(必須是 T 與 U 中同時存在的鍵)\n * Pick a specified key set K (must be keys that exist in both T and U)\n */\nexport type ITSPickBoth<T, U, K extends ITSKeyofBothSame<T, U> = ITSKeyofBothSame<T, U>> = Pick<T & U, K>;\n\n/**\n * 取得物件成員的類型\n * Get the type of an object member\n * \n * @see https://stackoverflow.com/questions/49198713/override-the-properties-of-an-interface-in-typescript\n */\nexport type ITSPickMember<T, K extends keyof T> = T[K];\n\n/**\n * 排除指定鍵(已棄用)\n * Exclude specified keys (deprecated)\n * \n * @deprecated 請使用 Omit 取代 / Please use Omit instead\n */\nexport type ITSPickNot<T, K extends keyof T> = Omit<T, K>;\n\n/**\n * 覆寫物件類型的屬性\n * Overwrite properties of an object type\n * \n * 用 U 中的屬性覆寫 T 中的同名屬性\n * Overwrites properties in T with the same name from U\n * \n * @see https://stackoverflow.com/questions/49198713/override-the-properties-of-an-interface-in-typescript\n * \n * @example\n * interface A1 { s: string }\n * type A2 = ITSOverwrite<A1, { s: number }>;\n * // type A2 = { s: number }\n */\nexport type ITSOverwrite<T, U> = Omit<T, keyof U> & U;\n\n/**\n * 合併兩個物件類型,處理衝突屬性\n * Merge two object types, handling conflicting properties\n * \n * 對於 T 與 U 中同時存在的鍵,取兩者的聯集類型\n * For keys that exist in both T and U, takes the union type of both\n * \n * @example\n * type Test1 = { id: number, code: string }\n * type Test2 = { id: string, code: number }\n * type Test3 = ITSMergeBoth<Test1, Test2>\n * // type Test3 = { id: string | number; code: string | number }\n * @see https://github.com/microsoft/TypeScript/issues/35627\n */\nexport type ITSMergeBoth<T, U> = ITSPickBothDiff<T, U> & Pick<T | U, ITSKeyofBothSame<T, U>>;\n\n/**\n * 選擇指定鍵並設為必填\n * Pick specified keys and mark as Required\n * \n * @example\n * interface User { name?: string; age?: number; email?: string; }\n * type RequiredName = ITSRequiredPick<User, 'name'>;\n * // type RequiredName = { name: string; age?: number; email?: string; }\n */\nexport type ITSRequiredPick<T, K extends keyof T = keyof T> = {\n\t[P in K]-?: T[P];\n};\n\n/**\n * 選擇指定鍵並設為可選\n * Pick specified keys and mark as Partial\n * \n * @example\n * interface User { name: string; age: number; email: string; }\n * type PartialName = ITSPartialPick<User, 'name'>;\n * // type PartialName = { name?: string; age: number; email: string; }\n */\nexport type ITSPartialPick<T, K extends keyof T = keyof T> = {\n\t[P in K]?: T[P];\n};\n\n/**\n * 複製類型並將指定鍵RK設為必填,其他鍵Pk設為可選\n * Clone a type and mark specified keys as Required, other keys as Partial\n * \n * @example\n * interface User { name: string; age: number; email: string; }\n * type Result = ITSPickExtra<User, 'name', 'email'>;\n * // type Result = { name: string; } & { age?: number; email?: string; }\n */\nexport type ITSPickExtra<T, RK extends keyof T, PK extends Exclude<keyof T, RK> = Exclude<keyof T, RK>> =\n\tITSRequiredPick<T, RK>\n\t& ITSPartialPick<T, PK>;\n\n/**\n * 複製類型並將指定鍵Pk設為可選,其他鍵Rk設為必填(與 ITSPickExtra 相反)\n * Clone a type and mark specified keys as Partial, other keys as Required (opposite of ITSPickExtra)\n * \n * @example\n * interface User { name: string; age: number; email: string; }\n * type Result = ITSPickExtra2<User, 'name', 'email'>;\n * // type Result = { name?: string; } & { age: number; email: string; }\n */\nexport type ITSPickExtra2<T, PK extends keyof T, RK extends Exclude<keyof T, PK> = Exclude<keyof T, PK>> =\n\tITSRequiredPick<T, RK>\n\t& ITSPartialPick<T, PK>;\n\n/**\n * 保留指定鍵不變(維持原本的必選/可選/唯讀屬性),其他鍵變為可選\n * Keep specified keys unchanged (preserving required/optional/readonly modifiers), other keys become Partial\n *\n * 與 ITSPickExtra 的差異:ITSPickExtra 會將指定鍵強制設為必填,而此類型保留原始修飾符\n * Difference from ITSPickExtra: ITSPickExtra forces specified keys to Required, while this type preserves original modifiers\n *\n * @see {@link ITSPickExtra} - 將指定鍵設為必填,其他鍵可選\n * @see {@link ITSPartialWith} - 將指定鍵設為可選,其他鍵不變\n *\n * @example\n * interface User { name: string; readonly id: string; age?: number; email: string; }\n * type Result = ITSPickAndPartialOther<User, 'name' | 'id'>;\n * // 輸出結果 / Output:\n * // { name: string; readonly id: string; } & { age?: number; email?: string; }\n * // 注意:name 維持必選,id 維持唯讀且必選,age 和 email 變為可選\n */\nexport type ITSPickAndPartialOther<T, RK extends keyof T, PK extends Exclude<keyof T, RK> = Exclude<keyof T, RK>> = Pick<T, RK>\n\t& ITSPartialPick<T, PK>;\n\n/**\n * 保留指定鍵為必填,其他鍵不變\n * Keep specified keys as Required, other keys unchanged\n * \n * @example\n * interface User { name: string; age: number; email: string; }\n * type Result = ITSRequiredWith<User, 'name'>;\n * // type Result = { name: string; age: number; email: string; }\n */\nexport type ITSRequiredWith<T, K extends keyof T> = Omit<T, K> & ITSRequiredPick<T, K>;\n\n/**\n * 保留指定鍵為可選,其他鍵不變\n * Keep specified keys as Partial, other keys unchanged\n * \n * @example\n * interface User { name: string; age: number; email: string; }\n * type Result = ITSPartialWith<User, 'name'>;\n * // type Result = { name?: string; age: number; email: string; }\n */\nexport type ITSPartialWith<T, K extends keyof T> = Omit<T, K> & ITSPartialPick<T, K>;\n\n/**\n * 確保物件至少具有指定的鍵集合中的一個\n * Ensure the object has at least one of the specified key sets\n * \n * @see https://stackoverflow.com/questions/40510611/typescript-interface-require-one-of-two-properties-to-exist\n * \n * @example\n * interface User { name?: string; age?: number; }\n * type AtLeastOne = ITSRequireAtLeastOne<User, 'name' | 'age'>;\n * // 需要至少提供 name 或 age 其中一個\n */\nexport type ITSRequireAtLeastOne<T, Keys extends keyof T = keyof T> =\n\tOmit<T, Keys>\n\t& {\n\t[K in Keys]-?: ITSRequiredPick<T, K>\n\t& ITSPartialPick<T, Exclude<Keys, K>>\n}[Keys];\n\n/**\n * 確保物件只能具有指定的鍵集合中的其中一個(互斥)\n * Ensure the object can only have exactly one of the specified key sets (mutually exclusive)\n *\n * @see https://stackoverflow.com/questions/40510611/typescript-interface-require-one-of-two-properties-to-exist\n * @see {@link ITSPickOne} 另一種實現方式,使用 `void` 作為其餘鍵的類型\n *\n * @example\n * interface User { name?: string; age?: number; }\n * type OnlyOne1 = ITSRequireOnlyOne<User, 'name' | 'age'>;\n * // 輸出結果:\n * // type OnlyOne1 = { name: string; age?: never; } | { age: number; name?: never; }\n * // 只能提供 name 或 age 其中一個,不能同時提供\n */\nexport type ITSRequireOnlyOne<T, Keys extends keyof T = keyof T> =\n\tOmit<T, Keys>\n\t& {\n\t[K in Keys]-?: ITSRequiredPick<T, K>\n\t& Partial<Record<Exclude<Keys, K>, never>>\n}[Keys];\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-type",
3
- "version": "3.0.10",
3
+ "version": "3.0.13",
4
4
  "description": "TypeScript 類型工具庫:提供豐富的類型操作工具和重新導出的內建類型 / TypeScript type utility library: provides rich type manipulation utilities and re-exported built-in types",
5
5
  "keywords": [
6
6
  ".d.ts",
@@ -64,12 +64,12 @@
64
64
  "test:jest:snapshot": "yarn run test:jest -- -u",
65
65
  "test:snapshot": "yarn run test -- -u",
66
66
  "test:tsd": "tsd",
67
- "build": "yarn run build-lib-toc",
67
+ "build": "yarn run build-lib-toc && tsc",
68
68
  "build-lib-toc": "ts-node ./test/script/toc && yarn run build:toc",
69
69
  "build:toc": "tsc --skipLibCheck & echo build:toc",
70
70
  "preversion": "yarn run test && yarn run postpublish:git:commit",
71
71
  "prepublishOnly": "echo prepublishOnly",
72
- "postpublish:git:commit": "git commit -m \"build(release): publish\" ./lib/index.d.ts & echo postpublish:git:commit",
72
+ "postpublish:git:commit": "git commit -m \"build(release): publish\" ./lib/index.d.ts ./lib & echo postpublish:git:commit",
73
73
  "ncu": "yarn-tool ncu -u",
74
74
  "sort-package-json": "yarn-tool sort",
75
75
  "ts:check": "tsc -p tsconfig.check.json --emitDeclarationOnly --skipLibCheck",
@@ -91,11 +91,11 @@
91
91
  },
92
92
  "dependencies": {
93
93
  "@types/node": "*",
94
- "tslib": ">=2",
94
+ "tslib": ">=2.8.1",
95
95
  "typedarray-dts": "^1.0.0"
96
96
  },
97
97
  "peerDependencies": {
98
98
  "ts-toolbelt": "^9.6.0"
99
99
  },
100
- "gitHead": "c87f657dc8050a9b9c3ed646262f6c497a867f05"
100
+ "gitHead": "846599bb59d03aa7a3caddc479886b3c602d6280"
101
101
  }