ts-type 3.0.8 → 3.0.10
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 +15 -0
- package/docs/10-same-logic-diff-impl.md +1150 -0
- package/docs/README.md +11 -0
- package/lib/_build-in.d.ts +64 -0
- package/lib/_build-in.js.map +1 -1
- package/lib/generic.d.ts +8 -0
- package/lib/generic.js.map +1 -1
- package/lib/helper/record/pick-one.d.ts +7 -0
- package/lib/helper/record/pick-one.js.map +1 -1
- package/lib/type/record.d.ts +4 -1
- package/lib/type/record.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,1150 @@
|
|
|
1
|
+
# 相同邏輯的不同實現 / Different Implementations of Same Logic
|
|
2
|
+
|
|
3
|
+
本文件記錄了功能相似但實現方式不同的類型,幫助開發者選擇適合的類型。
|
|
4
|
+
|
|
5
|
+
This document records types with similar functionality but different implementations, helping developers choose the appropriate type.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. 互斥鍵 / Mutually Exclusive Keys
|
|
10
|
+
|
|
11
|
+
確保物件只能具有指定鍵集合中的其中一個。
|
|
12
|
+
|
|
13
|
+
### ITSPickOne
|
|
14
|
+
|
|
15
|
+
- **位置**: `lib/helper/record/pick-one.ts`
|
|
16
|
+
- **輸出**: 使用 `void` 作為其餘鍵的類型
|
|
17
|
+
- **特點**: 較舊的實現方式
|
|
18
|
+
|
|
19
|
+
**原始碼**:
|
|
20
|
+
```ts
|
|
21
|
+
export type ITSPickOne<T, Keys extends keyof T = keyof T> = {
|
|
22
|
+
[K in Keys]: Record<K, T[K]> & ITSPartialRecord<Exclude<keyof T, K>, void>
|
|
23
|
+
}[Keys]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**範例**:
|
|
27
|
+
```ts
|
|
28
|
+
interface User { name?: string; age?: number; }
|
|
29
|
+
type OnlyOne = ITSPickOne<User, 'name' | 'age'>;
|
|
30
|
+
// 輸出結果:
|
|
31
|
+
// type OnlyOne = { name: string; age?: void; } | { age: number; name?: void; }
|
|
32
|
+
|
|
33
|
+
// 有效
|
|
34
|
+
const user1: OnlyOne = { name: 'John' };
|
|
35
|
+
const user2: OnlyOne = { age: 25 };
|
|
36
|
+
|
|
37
|
+
// 無效 - 不能同時提供多個
|
|
38
|
+
// const user3: OnlyOne = { name: 'John', age: 25 }; // Error!
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### ITSRequireOnlyOne
|
|
42
|
+
|
|
43
|
+
- **位置**: `lib/type/record.ts`
|
|
44
|
+
- **輸出**: 使用 `never` 作為其餘鍵的類型
|
|
45
|
+
- **特點**: 推薦使用,`never` 類型更加嚴格
|
|
46
|
+
|
|
47
|
+
**原始碼**:
|
|
48
|
+
```ts
|
|
49
|
+
export type ITSRequireOnlyOne<T, Keys extends keyof T = keyof T> =
|
|
50
|
+
Omit<T, Keys>
|
|
51
|
+
& {
|
|
52
|
+
[K in Keys]-?: ITSRequiredPick<T, K>
|
|
53
|
+
& Partial<Record<Exclude<Keys, K>, never>>
|
|
54
|
+
}[Keys];
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**範例**:
|
|
58
|
+
```ts
|
|
59
|
+
interface User { name?: string; age?: number; }
|
|
60
|
+
type OnlyOne = ITSRequireOnlyOne<User, 'name' | 'age'>;
|
|
61
|
+
// 輸出結果:
|
|
62
|
+
// type OnlyOne = { name: string; age?: never; } | { age: number; name?: never; }
|
|
63
|
+
|
|
64
|
+
// 有效
|
|
65
|
+
const user1: OnlyOne = { name: 'John' };
|
|
66
|
+
const user2: OnlyOne = { age: 25 };
|
|
67
|
+
|
|
68
|
+
// 無效 - 不能同時提供多個
|
|
69
|
+
// const user3: OnlyOne = { name: 'John', age: 25 }; // Error!
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 2. 部分鍵檢測 / Partial Key Detection
|
|
75
|
+
|
|
76
|
+
檢測物件中哪些鍵是可選的。
|
|
77
|
+
|
|
78
|
+
### ITSKeyIsPartialOfRecord
|
|
79
|
+
|
|
80
|
+
- **位置**: `lib/helper/record/partial.ts`
|
|
81
|
+
- **功能**: 檢測指定鍵是否為可選鍵
|
|
82
|
+
|
|
83
|
+
**原始碼**:
|
|
84
|
+
```ts
|
|
85
|
+
export type ITSKeyIsPartialOfRecord<T, K extends keyof T> = Omit<T, K> extends T ? K : never;
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**範例**:
|
|
89
|
+
```ts
|
|
90
|
+
// 範例 1: age 是可選鍵
|
|
91
|
+
interface User { name: string; age?: number; }
|
|
92
|
+
type PartialKeys = ITSKeyIsPartialOfRecord<User, 'age'>;
|
|
93
|
+
// 輸出結果:type PartialKeys = "age"
|
|
94
|
+
|
|
95
|
+
// 範例 2: name 是必填鍵
|
|
96
|
+
type PartialKeys2 = ITSKeyIsPartialOfRecord<User, 'name'>;
|
|
97
|
+
// 輸出結果:type PartialKeys2 = never
|
|
98
|
+
|
|
99
|
+
// 範例 3: 檢測多個鍵
|
|
100
|
+
type PartialKeys3 = ITSKeyIsPartialOfRecord<User, 'name' | 'age'>;
|
|
101
|
+
// 輸出結果:type PartialKeys3 = "age"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### ITSPartialRecord
|
|
105
|
+
|
|
106
|
+
- **位置**: `lib/type/record/partial.ts`
|
|
107
|
+
- **功能**: 建立可選的記錄類型
|
|
108
|
+
|
|
109
|
+
**原始碼**:
|
|
110
|
+
```ts
|
|
111
|
+
export type ITSPartialRecord<K extends keyof any, T> = {
|
|
112
|
+
[P in K]?: T;
|
|
113
|
+
};
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**範例**:
|
|
117
|
+
```ts
|
|
118
|
+
// 範例 1: 基礎用法
|
|
119
|
+
type PartialUser = ITSPartialRecord<'name' | 'age', string>;
|
|
120
|
+
// 輸出結果:type PartialUser = { name?: string; age?: string; }
|
|
121
|
+
|
|
122
|
+
// 範例 2: 與具體鍵一起使用
|
|
123
|
+
interface Config { host: string; port: number; }
|
|
124
|
+
type PartialConfig = ITSPartialRecord<keyof Config, string>;
|
|
125
|
+
// 輸出結果:type PartialConfig = { host?: string; port?: string; }
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### ITSRequireRecord
|
|
129
|
+
|
|
130
|
+
- **位置**: `lib/type/record/partial.ts`
|
|
131
|
+
- **功能**: 建立必填的記錄類型
|
|
132
|
+
|
|
133
|
+
**原始碼**:
|
|
134
|
+
```ts
|
|
135
|
+
export type ITSRequireRecord<K extends keyof any, T> = {
|
|
136
|
+
[P in K]-?: T;
|
|
137
|
+
};
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**範例**:
|
|
141
|
+
```ts
|
|
142
|
+
// 範例 1: 基礎用法
|
|
143
|
+
type RequiredUser = ITSRequireRecord<'name' | 'age', string>;
|
|
144
|
+
// 輸出結果:type RequiredUser = { name: string; age: string; }
|
|
145
|
+
|
|
146
|
+
// 範例 2: 數字類型
|
|
147
|
+
type RequiredAges = ITSRequireRecord<'age' | 'score', number>;
|
|
148
|
+
// 輸出結果:type RequiredAges = { age: number; score: number; }
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 3. 唯讀屬性操作 / Readonly Property Operations
|
|
154
|
+
|
|
155
|
+
### 類型級別 (Type-level) - 操作整個類型
|
|
156
|
+
|
|
157
|
+
**ITSReadonlyPartial** (`lib/helper/readonly.ts`)
|
|
158
|
+
|
|
159
|
+
**原始碼**:
|
|
160
|
+
```ts
|
|
161
|
+
export type ITSReadonlyPartial<T> = {
|
|
162
|
+
readonly [P in keyof T]?: T[P]
|
|
163
|
+
};
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**範例**:
|
|
167
|
+
```ts
|
|
168
|
+
interface User { name: string; age: number; }
|
|
169
|
+
type Result = ITSReadonlyPartial<User>;
|
|
170
|
+
// 輸出結果:type Result = { readonly name?: string; readonly age?: number; }
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
**ITSWriteable** (`lib/helper/readonly.ts`)
|
|
176
|
+
|
|
177
|
+
**原始碼**:
|
|
178
|
+
```ts
|
|
179
|
+
export type ITSWriteable<T> = ITSWriteablePick<T, keyof T>;
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**範例**:
|
|
183
|
+
```ts
|
|
184
|
+
interface User { readonly name: string; readonly age: number; }
|
|
185
|
+
type Result = ITSWriteable<User>;
|
|
186
|
+
// 輸出結果:type Result = { name: string; age: number; }
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
**ITSReadonlyPick** (`lib/helper/readonly.ts`)
|
|
192
|
+
|
|
193
|
+
**原始碼**:
|
|
194
|
+
```ts
|
|
195
|
+
export type ITSReadonlyPick<T, K extends keyof T = keyof T> = {
|
|
196
|
+
readonly [P in K]: T[P];
|
|
197
|
+
};
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**範例**:
|
|
201
|
+
```ts
|
|
202
|
+
interface User { name: string; age: number; email: string; }
|
|
203
|
+
type Result = ITSReadonlyPick<User, 'name'>;
|
|
204
|
+
// 輸出結果:type Result = { readonly name: string; age: number; email: string; }
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
**ITSWriteablePick** (`lib/helper/readonly.ts`)
|
|
210
|
+
|
|
211
|
+
**原始碼**:
|
|
212
|
+
```ts
|
|
213
|
+
export type ITSWriteablePick<T, K extends keyof T = keyof T> = {
|
|
214
|
+
-readonly [P in K]: T[P];
|
|
215
|
+
};
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**範例**:
|
|
219
|
+
```ts
|
|
220
|
+
interface User { readonly name: string; readonly age: number; readonly email: string; }
|
|
221
|
+
type Result = ITSWriteablePick<User, 'name' | 'age'>;
|
|
222
|
+
// 輸出結果:type Result = { name: string; age: number; readonly email: string; }
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
**ITSReadonlyWith** (`lib/helper/readonly.ts`)
|
|
228
|
+
|
|
229
|
+
**原始碼**:
|
|
230
|
+
```ts
|
|
231
|
+
export type ITSReadonlyWith<T, K extends keyof T = keyof T> = Omit<T, K> & ITSReadonlyPick<T, K>;
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**範例**:
|
|
235
|
+
```ts
|
|
236
|
+
interface User { name: string; age: number; email: string; }
|
|
237
|
+
type Result = ITSReadonlyWith<User, 'name' | 'age'>;
|
|
238
|
+
// 輸出結果:type Result = { readonly name: string; readonly age: number; email: string; }
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
**ITSWriteableWith** (`lib/helper/readonly.ts`)
|
|
244
|
+
|
|
245
|
+
**原始碼**:
|
|
246
|
+
```ts
|
|
247
|
+
export type ITSWriteableWith<T, K extends keyof T = keyof T> = Omit<T, K> & ITSWriteablePick<T, K>;
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**範例**:
|
|
251
|
+
```ts
|
|
252
|
+
interface User { readonly name: string; readonly age: number; email: string; }
|
|
253
|
+
type Result = ITSWriteableWith<User, 'email'>;
|
|
254
|
+
// 輸出結果:type Result = { readonly name: string; readonly age: number; email: string; }
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
### 記錄級別 (Record-level) - 操作鍵集合
|
|
260
|
+
|
|
261
|
+
**ITSReadonlyRecord** (`lib/type/record/readonly.ts`)
|
|
262
|
+
|
|
263
|
+
**原始碼**:
|
|
264
|
+
```ts
|
|
265
|
+
export type ITSReadonlyRecord<K extends keyof any, T> = {
|
|
266
|
+
readonly [P in K]: T;
|
|
267
|
+
};
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**範例**:
|
|
271
|
+
```ts
|
|
272
|
+
type Result = ITSReadonlyRecord<'name' | 'age', string>;
|
|
273
|
+
// 輸出結果:type Result = { readonly name: string; readonly age: string; }
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
**ITSWriteableRecord** (`lib/type/record/readonly.ts`)
|
|
279
|
+
|
|
280
|
+
**原始碼**:
|
|
281
|
+
```ts
|
|
282
|
+
export type ITSWriteableRecord<K extends keyof any, T> = {
|
|
283
|
+
-readonly [P in K]: T;
|
|
284
|
+
};
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**範例**:
|
|
288
|
+
```ts
|
|
289
|
+
type Result = ITSWriteableRecord<'name' | 'age', string>;
|
|
290
|
+
// 輸出結果:type Result = { name: string; age: string; }
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## 4. 必填/可選鍵選擇 / Required/Optional Key Pick
|
|
296
|
+
|
|
297
|
+
### ITSRequiredPick
|
|
298
|
+
|
|
299
|
+
- **位置**: `lib/type/record.ts`
|
|
300
|
+
- **功能**: 選擇指定鍵並設為必填
|
|
301
|
+
|
|
302
|
+
**原始碼**:
|
|
303
|
+
```ts
|
|
304
|
+
export type ITSRequiredPick<T, K extends keyof T = keyof T> = {
|
|
305
|
+
[P in K]-?: T[P];
|
|
306
|
+
} & Omit<T, K>;
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**範例**:
|
|
310
|
+
```ts
|
|
311
|
+
interface User { name?: string; age?: number; email?: string; }
|
|
312
|
+
type Result = ITSRequiredPick<User, 'name'>;
|
|
313
|
+
// 輸出結果:type Result = { name: string; age?: number; email?: string; }
|
|
314
|
+
|
|
315
|
+
// 多個鍵
|
|
316
|
+
type Result2 = ITSRequiredPick<User, 'name' | 'age'>;
|
|
317
|
+
// 輸出結果:type Result2 = { name: string; age: number; email?: string; }
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
### ITSPartialPick
|
|
323
|
+
|
|
324
|
+
- **位置**: `lib/type/record.ts`
|
|
325
|
+
- **功能**: 選擇指定鍵並設為可選
|
|
326
|
+
|
|
327
|
+
**原始碼**:
|
|
328
|
+
```ts
|
|
329
|
+
export type ITSPartialPick<T, K extends keyof T = keyof T> = {
|
|
330
|
+
[P in K]?: T[P];
|
|
331
|
+
} & Omit<T, K>;
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**範例**:
|
|
335
|
+
```ts
|
|
336
|
+
interface User { name: string; age: number; email: string; }
|
|
337
|
+
type Result = ITSPartialPick<User, 'name'>;
|
|
338
|
+
// 輸出結果:type Result = { name?: string; age: number; email: string; }
|
|
339
|
+
|
|
340
|
+
// 多個鍵
|
|
341
|
+
type Result2 = ITSPartialPick<User, 'name' | 'age'>;
|
|
342
|
+
// 輸出結果:type Result2 = { name?: string; age?: number; email: string; }
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
### ITSRequiredWith
|
|
348
|
+
|
|
349
|
+
- **位置**: `lib/type/record.ts`
|
|
350
|
+
- **功能**: 保留其他鍵的同時,將指定鍵設為必填
|
|
351
|
+
|
|
352
|
+
**原始碼**:
|
|
353
|
+
```ts
|
|
354
|
+
export type ITSRequiredWith<T, K extends keyof T> = Omit<T, K> & ITSRequiredPick<T, K>;
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
**範例**:
|
|
358
|
+
```ts
|
|
359
|
+
interface User { name?: string; age?: number; email?: string; }
|
|
360
|
+
type Result = ITSRequiredWith<User, 'name'>;
|
|
361
|
+
// 輸出結果:type Result = { name: string; age?: number; email?: string; }
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
### ITSPartialWith
|
|
367
|
+
|
|
368
|
+
- **位置**: `lib/type/record.ts`
|
|
369
|
+
- **功能**: 保留其他鍵的同時,將指定鍵設為可選
|
|
370
|
+
|
|
371
|
+
**原始碼**:
|
|
372
|
+
```ts
|
|
373
|
+
export type ITSPartialWith<T, K extends keyof T> = Omit<T, K> & ITSPartialPick<T, K>;
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**範例**:
|
|
377
|
+
```ts
|
|
378
|
+
interface User { name: string; age: number; email: string; }
|
|
379
|
+
type Result = ITSPartialWith<User, 'name'>;
|
|
380
|
+
// 輸出結果:type Result = { name?: string; age: number; email: string; }
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
### ITSPickExtra
|
|
386
|
+
|
|
387
|
+
- **位置**: `lib/type/record.ts`
|
|
388
|
+
- **功能**: 部分必填、部分可選的鍵選擇
|
|
389
|
+
|
|
390
|
+
**原始碼**:
|
|
391
|
+
```ts
|
|
392
|
+
export type ITSPickExtra<T, RK extends keyof T, PK extends Exclude<keyof T, RK> = Exclude<keyof T, RK>> =
|
|
393
|
+
ITSRequiredPick<T, RK> & ITSPartialPick<T, PK>;
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
**範例**:
|
|
397
|
+
```ts
|
|
398
|
+
interface User { name: string; age: number; email: string; }
|
|
399
|
+
|
|
400
|
+
// 必填 name,其餘可選
|
|
401
|
+
type Result = ITSPickExtra<User, 'name', 'age'>;
|
|
402
|
+
// 輸出結果:type Result = { name: string; age?: number; email?: string; }
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
### ITSPickExtra2
|
|
408
|
+
|
|
409
|
+
- **位置**: `lib/type/record.ts`
|
|
410
|
+
- **功能**: 部分必填、部分可選的鍵選擇(參數順序相反)
|
|
411
|
+
|
|
412
|
+
**原始碼**:
|
|
413
|
+
```ts
|
|
414
|
+
export type ITSPickExtra2<T, PK extends keyof T, RK extends Exclude<keyof T, PK> = Exclude<keyof T, PK>> =
|
|
415
|
+
ITSRequiredPick<T, RK> & ITSPartialPick<T, PK>;
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**範例**:
|
|
419
|
+
```ts
|
|
420
|
+
interface User { name: string; age: number; email: string; }
|
|
421
|
+
|
|
422
|
+
// 必填 age | email,其餘可選
|
|
423
|
+
type Result2 = ITSPickExtra2<User, 'age' | 'email'>;
|
|
424
|
+
// 輸出結果:type Result2 = { name?: string; age: number; email: number; }
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## 5. 空類型 / Empty Types
|
|
430
|
+
|
|
431
|
+
### ITSEmptyRecord
|
|
432
|
+
|
|
433
|
+
- **位置**: `lib/type/record/empty.ts`
|
|
434
|
+
- **功能**: 建立空記錄類型
|
|
435
|
+
|
|
436
|
+
**原始碼**:
|
|
437
|
+
```ts
|
|
438
|
+
export type ITSEmptyRecord = Record<PropertyKey, never>;
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
**範例**:
|
|
442
|
+
```ts
|
|
443
|
+
type Empty = ITSEmptyRecord;
|
|
444
|
+
// 輸出結果:type Empty = Record<PropertyKey, never>
|
|
445
|
+
|
|
446
|
+
// 等價於
|
|
447
|
+
type Empty2 = { [key: string]: never };
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
### ITSEmptyRecordByKeys
|
|
453
|
+
|
|
454
|
+
- **位置**: `lib/type/record/empty.ts`
|
|
455
|
+
- **功能**: 建立具有指定鍵的空記錄
|
|
456
|
+
|
|
457
|
+
**原始碼**:
|
|
458
|
+
```ts
|
|
459
|
+
export type ITSEmptyRecordByKeys<K extends PropertyKey> = Record<K, never>;
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
**範例**:
|
|
463
|
+
```ts
|
|
464
|
+
type EmptyByKeys = ITSEmptyRecordByKeys<'a' | 'b'>;
|
|
465
|
+
// 輸出結果:type EmptyByKeys = { a: never; b: never; }
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
### ITSLogicIsEmptyRecord
|
|
471
|
+
|
|
472
|
+
- **位置**: `lib/logic/record/empty.ts`
|
|
473
|
+
- **功能**: 判斷類型是否為空記錄
|
|
474
|
+
|
|
475
|
+
**原始碼**:
|
|
476
|
+
```ts
|
|
477
|
+
export type ITSLogicIsEmptyRecord<T, Y = true, N = false> = T extends ITSEmptyRecord ? Y : N
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
**範例**:
|
|
481
|
+
```ts
|
|
482
|
+
type Result1 = ITSLogicIsEmptyRecord<Record<PropertyKey, never>>;
|
|
483
|
+
// 輸出結果:type Result1 = true
|
|
484
|
+
|
|
485
|
+
type Result2 = ITSLogicIsEmptyRecord<{ a: string }>;
|
|
486
|
+
// 輸出結果:type Result2 = false
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
### ITSEmptyTuple
|
|
492
|
+
|
|
493
|
+
- **位置**: `lib/type/tuple/empty.ts`
|
|
494
|
+
- **功能**: 空元組類型
|
|
495
|
+
|
|
496
|
+
**原始碼**:
|
|
497
|
+
```ts
|
|
498
|
+
export type ITSEmptyTuple = ITSArrayListMaybeReadonly<never>;
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
**範例**:
|
|
502
|
+
```ts
|
|
503
|
+
type Empty = ITSEmptyTuple;
|
|
504
|
+
// 輸出結果:type Empty = [] | readonly []
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## 6. 列舉操作 / Enum Operations
|
|
510
|
+
|
|
511
|
+
### ITSEnumLike
|
|
512
|
+
|
|
513
|
+
- **位置**: `lib/type/record/enum.ts`
|
|
514
|
+
- **功能**: 定義列舉類型的基礎設施
|
|
515
|
+
|
|
516
|
+
**原始碼**:
|
|
517
|
+
```ts
|
|
518
|
+
export type ITSEnumLike<K extends string = string, V extends string | number = string | number> =
|
|
519
|
+
ITSReadonlyRecord<K, V> | (V extends number ? ITSNumberEnumLikeReverse<K, Exclude<V, string>> : ITSEnumLikeReverseExcludeNumber);
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
**範例**:
|
|
523
|
+
```ts
|
|
524
|
+
// 字串列舉
|
|
525
|
+
enum EnumString { A = 'a', B = 'b' }
|
|
526
|
+
type T1 = ITSEnumLike<EnumString>;
|
|
527
|
+
// 輸出結果:type T1 = ...
|
|
528
|
+
|
|
529
|
+
// 數字列舉
|
|
530
|
+
enum EnumNumber { A = 1, B = 2 }
|
|
531
|
+
type T2 = ITSNumberEnumLike<EnumNumber>;
|
|
532
|
+
// 輸出結果:type T2 = ...
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
### ITSExcludeEnumValue
|
|
538
|
+
|
|
539
|
+
- **位置**: `lib/helper/record/enum.ts`
|
|
540
|
+
- **功能**: 從列舉類型中排除指定值
|
|
541
|
+
|
|
542
|
+
**原始碼**:
|
|
543
|
+
```ts
|
|
544
|
+
export type ITSExcludeEnumValue<Enum extends ITSEnumLike, U extends ITSValueOf<Enum>> = Exclude<ITSValueOf<Enum>, U>;
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
**範例**:
|
|
548
|
+
```ts
|
|
549
|
+
enum Color { Red, Green, Blue }
|
|
550
|
+
type ExcludedRed = ITSExcludeEnumValue<Color, Color.Red>;
|
|
551
|
+
// 輸出結果:type ExcludedRed = Color.Green | Color.Blue
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
---
|
|
555
|
+
|
|
556
|
+
### ITSExtractEnumValue
|
|
557
|
+
|
|
558
|
+
- **位置**: `lib/helper/record/enum.ts`
|
|
559
|
+
- **功能**: 從列舉類型中提取指定值
|
|
560
|
+
|
|
561
|
+
**原始碼**:
|
|
562
|
+
```ts
|
|
563
|
+
export type ITSExtractEnumValue<Enum extends ITSEnumLike, U extends ITSValueOf<Enum>> = Extract<ITSValueOf<Enum>, U>;
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
**範例**:
|
|
567
|
+
```ts
|
|
568
|
+
enum Color { Red, Green, Blue }
|
|
569
|
+
type ExtractedRed = ITSExtractEnumValue<Color, Color.Red>;
|
|
570
|
+
// 輸出結果:type ExtractedRed = Color.Red
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
---
|
|
574
|
+
|
|
575
|
+
### ITSNumberEnumToNumber
|
|
576
|
+
|
|
577
|
+
- **位置**: `lib/helper/record/enum.ts`
|
|
578
|
+
- **功能**: 將數字列舉轉換為純數字類型
|
|
579
|
+
|
|
580
|
+
**原始碼**:
|
|
581
|
+
```ts
|
|
582
|
+
export type ITSNumberEnumToNumber<T extends number> = ITSStringInferToNumber<ITSToStringLiteral<Extract<T, number>>>
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
**範例**:
|
|
586
|
+
```ts
|
|
587
|
+
enum Status { Active = 1, Inactive = 2 }
|
|
588
|
+
type NumStatus = ITSNumberEnumToNumber<Status>;
|
|
589
|
+
// 輸出結果:type NumStatus = 1 | 2
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
### ITSNumberEnumAndNumber
|
|
595
|
+
|
|
596
|
+
- **位置**: `lib/helper/record/enum.ts`
|
|
597
|
+
- **功能**: 數字列舉與數字的聯合類型
|
|
598
|
+
|
|
599
|
+
**原始碼**:
|
|
600
|
+
```ts
|
|
601
|
+
export type ITSNumberEnumAndNumber<T extends number> = Extract<T, number> | ITSNumberEnumToNumber<T>
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
**範例**:
|
|
605
|
+
```ts
|
|
606
|
+
enum Status { Active = 1, Inactive = 2 }
|
|
607
|
+
type StatusValue = ITSNumberEnumAndNumber<Status>;
|
|
608
|
+
// 輸出結果:type StatusValue = 1 | 2 | number
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
613
|
+
## 7. 鍵提取 / Key Extraction
|
|
614
|
+
|
|
615
|
+
### ITSPickSame
|
|
616
|
+
|
|
617
|
+
- **位置**: `lib/type/record.ts`
|
|
618
|
+
- **功能**: 選擇 T 中與 U 相同的鍵
|
|
619
|
+
|
|
620
|
+
**原始碼**:
|
|
621
|
+
```ts
|
|
622
|
+
export type ITSPickSame<T, U> = Pick<T, ITSKeyofSame<T, U>>;
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
**範例**:
|
|
626
|
+
```ts
|
|
627
|
+
type A = { a: 1; b: 2; c: 3 };
|
|
628
|
+
type B = { a: 3; c: 4; d: 5 };
|
|
629
|
+
type Same = ITSPickSame<A, B>;
|
|
630
|
+
// 輸出結果:type Same = { a: 1; c: 3 }
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
---
|
|
634
|
+
|
|
635
|
+
### ITSPickDiff
|
|
636
|
+
|
|
637
|
+
- **位置**: `lib/type/record.ts`
|
|
638
|
+
- **功能**: 選擇 T 中與 U 不同的鍵
|
|
639
|
+
|
|
640
|
+
**原始碼**:
|
|
641
|
+
```ts
|
|
642
|
+
export type ITSPickDiff<T, U> = Pick<T, ITSKeyofDiff<T, U>>;
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
**範例**:
|
|
646
|
+
```ts
|
|
647
|
+
type A = { a: 1; b: 2; c: 3 };
|
|
648
|
+
type B = { a: 3; c: 4; d: 5 };
|
|
649
|
+
type Diff = ITSPickDiff<A, B>;
|
|
650
|
+
// 輸出結果:type Diff = { b: 2 }
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
---
|
|
654
|
+
|
|
655
|
+
### ITSPickBothSame
|
|
656
|
+
|
|
657
|
+
- **位置**: `lib/type/record.ts`
|
|
658
|
+
- **功能**: 選擇 T 和 U 共同擁有的鍵
|
|
659
|
+
|
|
660
|
+
**原始碼**:
|
|
661
|
+
```ts
|
|
662
|
+
export type ITSPickBothSame<T, U> = Pick<T & U, ITSKeyofBothSame<T, U>>;
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
**範例**:
|
|
666
|
+
```ts
|
|
667
|
+
type A = { a: 1; b: 2; c: 3 };
|
|
668
|
+
type B = { a: 3; c: 4; d: 5 };
|
|
669
|
+
type BothSame = ITSPickBothSame<A, B>;
|
|
670
|
+
// 輸出結果:type BothSame = { a: 1 | 3; c: 3 | 4 }
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
---
|
|
674
|
+
|
|
675
|
+
### ITSKeyOfRecordExtractReadonly
|
|
676
|
+
|
|
677
|
+
- **位置**: `lib/helper/record.ts`
|
|
678
|
+
- **功能**: 取得物件的唯讀鍵集合
|
|
679
|
+
|
|
680
|
+
**原始碼**:
|
|
681
|
+
```ts
|
|
682
|
+
export type ITSKeyOfRecordExtractReadonly<T> = {[K in keyof T]-?: (<U>() => U extends {-readonly [P in K]: T[K]} ? 1 : 2) extends (<U>() => U extends {[P in K]: T[K]} ? 1 : 2) ? never : K}[keyof T];
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
**範例**:
|
|
686
|
+
```ts
|
|
687
|
+
interface Todo {
|
|
688
|
+
readonly title: string
|
|
689
|
+
readonly description: string
|
|
690
|
+
completed: boolean
|
|
691
|
+
}
|
|
692
|
+
type Keys = ITSKeyOfRecordExtractReadonly<Todo>;
|
|
693
|
+
// 輸出結果:type Keys = "title" | "description"
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
---
|
|
697
|
+
|
|
698
|
+
### ITSKeyOfRecordExcludeReadonly
|
|
699
|
+
|
|
700
|
+
- **位置**: `lib/helper/record.ts`
|
|
701
|
+
- **功能**: 取得物件的非唯讀鍵集合
|
|
702
|
+
|
|
703
|
+
**原始碼**:
|
|
704
|
+
```ts
|
|
705
|
+
export type ITSKeyOfRecordExcludeReadonly<T> = Exclude<keyof T, ITSKeyOfRecordExtractReadonly<T>>
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
**範例**:
|
|
709
|
+
```ts
|
|
710
|
+
interface Todo {
|
|
711
|
+
readonly title: string
|
|
712
|
+
readonly description: string
|
|
713
|
+
completed: boolean
|
|
714
|
+
}
|
|
715
|
+
type Keys = ITSKeyOfRecordExcludeReadonly<Todo>;
|
|
716
|
+
// 輸出結果:type Keys = "completed"
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
---
|
|
720
|
+
|
|
721
|
+
## 8. 覆寫與合併 / Overwrite & Merge
|
|
722
|
+
|
|
723
|
+
### ITSOverwrite
|
|
724
|
+
|
|
725
|
+
- **位置**: `lib/type/record.ts`
|
|
726
|
+
- **功能**: 用 U 中的屬性覆寫 T 中的同名屬性
|
|
727
|
+
|
|
728
|
+
**原始碼**:
|
|
729
|
+
```ts
|
|
730
|
+
export type ITSOverwrite<T, U> = Omit<T, keyof U> & U;
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
**範例**:
|
|
734
|
+
```ts
|
|
735
|
+
interface Config { host: string; port: number }
|
|
736
|
+
type Updated = ITSOverwrite<Config, { port: string }>;
|
|
737
|
+
// 輸出結果:type Updated = { host: string; port: string }
|
|
738
|
+
|
|
739
|
+
// 新增屬性
|
|
740
|
+
type Added = ITSOverwrite<Config, { timeout: number }>;
|
|
741
|
+
// 輸出結果:type Added = { host: string; port: number; timeout: number }
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
---
|
|
745
|
+
|
|
746
|
+
### ITSMergeBoth
|
|
747
|
+
|
|
748
|
+
- **位置**: `lib/type/record.ts`
|
|
749
|
+
- **功能**: 合併兩個物件類型,處理衝突屬性
|
|
750
|
+
|
|
751
|
+
**原始碼**:
|
|
752
|
+
```ts
|
|
753
|
+
export type ITSMergeBoth<T, U> = ITSPickBothDiff<T, U> & Pick<T | U, ITSKeyofBothSame<T, U>>;
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
**範例**:
|
|
757
|
+
```ts
|
|
758
|
+
type A = { id: number; code: string; x: boolean };
|
|
759
|
+
type B = { id: string; code: number; y: number };
|
|
760
|
+
type Result = ITSMergeBoth<A, B>;
|
|
761
|
+
// 輸出結果:type Result = { id: string | number; code: string | number; x: boolean; y: number }
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
---
|
|
765
|
+
|
|
766
|
+
## 9. 選擇性鍵 / Optional Keys
|
|
767
|
+
|
|
768
|
+
### ITSRequireAtLeastOne
|
|
769
|
+
|
|
770
|
+
- **位置**: `lib/type/record.ts`
|
|
771
|
+
- **功能**: 確保物件至少具有指定鍵集合中的一個
|
|
772
|
+
|
|
773
|
+
**原始碼**:
|
|
774
|
+
```ts
|
|
775
|
+
export type ITSRequireAtLeastOne<T, Keys extends keyof T = keyof T> =
|
|
776
|
+
Omit<T, Keys> & {
|
|
777
|
+
[K in Keys]-?: ITSRequiredPick<T, K>
|
|
778
|
+
& ITSPartialPick<T, Exclude<Keys, K>>
|
|
779
|
+
}[Keys];
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
**範例**:
|
|
783
|
+
```ts
|
|
784
|
+
interface User { name?: string; age?: number; }
|
|
785
|
+
type AtLeastOne = ITSRequireAtLeastOne<User, 'name' | 'age'>;
|
|
786
|
+
// 輸出結果:type AtLeastOne = { name: string; age?: never; } | { age: number; name?: never; }
|
|
787
|
+
|
|
788
|
+
// 有效
|
|
789
|
+
const user1: AtLeastOne = { name: 'John' };
|
|
790
|
+
const user2: AtLeastOne = { age: 25 };
|
|
791
|
+
const user3: AtLeastOne = { name: 'John', age: 25 }; // 也有效!
|
|
792
|
+
|
|
793
|
+
// 無效 - 必須至少提供一個
|
|
794
|
+
// const user4: AtLeastOne = {}; // Error!
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
---
|
|
798
|
+
|
|
799
|
+
### ITSPickNot
|
|
800
|
+
|
|
801
|
+
- **位置**: `lib/type/record.ts`
|
|
802
|
+
- **功能**: 排除指定鍵
|
|
803
|
+
|
|
804
|
+
**原始碼**:
|
|
805
|
+
```ts
|
|
806
|
+
export type ITSPickNot<T, K extends keyof T> = Omit<T, K>;
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
**範例**:
|
|
810
|
+
```ts
|
|
811
|
+
interface User { name: string; age: number; email: string; }
|
|
812
|
+
type WithoutName = ITSPickNot<User, 'name'>;
|
|
813
|
+
// 輸出結果:type WithoutName = { age: number; email: string; }
|
|
814
|
+
|
|
815
|
+
type WithoutNameAndAge = ITSPickNot<User, 'name' | 'age'>;
|
|
816
|
+
// 輸出結果:type WithoutNameAndAge = { email: string; }
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
---
|
|
820
|
+
|
|
821
|
+
## 10. 移除鍵 / Key Removal
|
|
822
|
+
|
|
823
|
+
### ITSOmitIndexSignatures
|
|
824
|
+
|
|
825
|
+
- **位置**: `lib/helper/record/omit-index.ts`
|
|
826
|
+
- **功能**: 移除索引簽名
|
|
827
|
+
|
|
828
|
+
**原始碼**:
|
|
829
|
+
```ts
|
|
830
|
+
export type ITSOmitIndexSignatures<T extends Record<any, any>> = {
|
|
831
|
+
[K in keyof T as {} extends Record<K, unknown> ? never : K]: T[K]
|
|
832
|
+
};
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
**範例**:
|
|
836
|
+
```ts
|
|
837
|
+
interface WithIndex { name: string; [key: string]: any; }
|
|
838
|
+
type WithoutIndex = ITSOmitIndexSignatures<WithIndex>;
|
|
839
|
+
// 輸出結果:type WithoutIndex = { name: string }
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
---
|
|
843
|
+
|
|
844
|
+
### ITSKnownKeys
|
|
845
|
+
|
|
846
|
+
- **位置**: `lib/helper/record/omit-index.ts`
|
|
847
|
+
- **功能**: 取得物件的已知鍵(排除索引簽名)
|
|
848
|
+
|
|
849
|
+
**原始碼**:
|
|
850
|
+
```ts
|
|
851
|
+
export type ITSKnownKeys<T extends Record<any, any>> = keyof ITSOmitIndexSignatures<T>;
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
**範例**:
|
|
855
|
+
```ts
|
|
856
|
+
interface WithIndex { name: string; [key: string]: any; }
|
|
857
|
+
type Known = ITSKnownKeys<WithIndex>;
|
|
858
|
+
// 輸出結果:type Known = "name"
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
---
|
|
862
|
+
|
|
863
|
+
## 11. 邏輯類型 / Logic Types
|
|
864
|
+
|
|
865
|
+
### ITSLogicIsAny
|
|
866
|
+
|
|
867
|
+
- **位置**: `lib/logic/any.ts`
|
|
868
|
+
- **功能**: 檢測是否為 any 類型
|
|
869
|
+
|
|
870
|
+
**原始碼**:
|
|
871
|
+
```ts
|
|
872
|
+
export type ITSLogicIsAny<T, Y = true, N = false> = 0 extends (1 & T) ? Y : N;
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
**範例**:
|
|
876
|
+
```ts
|
|
877
|
+
type Result1 = ITSLogicIsAny<any>;
|
|
878
|
+
// 輸出結果:type Result1 = true
|
|
879
|
+
|
|
880
|
+
type Result2 = ITSLogicIsAny<string>;
|
|
881
|
+
// 輸出結果:type Result2 = false
|
|
882
|
+
|
|
883
|
+
type Result3 = ITSLogicIsAny<unknown>;
|
|
884
|
+
// 輸出結果:type Result3 = false
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
---
|
|
888
|
+
|
|
889
|
+
### ITSLogicNotAny
|
|
890
|
+
|
|
891
|
+
- **位置**: `lib/logic/any.ts`
|
|
892
|
+
- **功能**: 檢測是否不為 any 類型
|
|
893
|
+
|
|
894
|
+
**原始碼**:
|
|
895
|
+
```ts
|
|
896
|
+
export type ITSLogicNotAny<T, Y = true, N = false> = ITSLogicIsAny<T, N, Y>;
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
**範例**:
|
|
900
|
+
```ts
|
|
901
|
+
type Result1 = ITSLogicNotAny<any>;
|
|
902
|
+
// 輸出結果:type Result1 = false
|
|
903
|
+
|
|
904
|
+
type Result2 = ITSLogicNotAny<string>;
|
|
905
|
+
// 輸出結果:type Result2 = true
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
---
|
|
909
|
+
|
|
910
|
+
### ITSLogicIsNever
|
|
911
|
+
|
|
912
|
+
- **位置**: `lib/logic/never.ts`
|
|
913
|
+
- **功能**: 檢測是否為 never 類型
|
|
914
|
+
|
|
915
|
+
**原始碼**:
|
|
916
|
+
```ts
|
|
917
|
+
export type ITSLogicIsNever<T, Y = true, N = false> = [T] extends [never] ? Y : N;
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
**範例**:
|
|
921
|
+
```ts
|
|
922
|
+
type Result1 = ITSLogicIsNever<never>;
|
|
923
|
+
// 輸出結果:type Result1 = true
|
|
924
|
+
|
|
925
|
+
type Result2 = ITSLogicIsNever<string>;
|
|
926
|
+
// 輸出結果:type Result2 = false
|
|
927
|
+
```
|
|
928
|
+
|
|
929
|
+
---
|
|
930
|
+
|
|
931
|
+
## 12. 陣列類型 / Array Types
|
|
932
|
+
|
|
933
|
+
### ITSValueOfArray
|
|
934
|
+
|
|
935
|
+
- **位置**: `lib/helper/key-value.ts`
|
|
936
|
+
- **功能**: 取得陣列的元素類型
|
|
937
|
+
|
|
938
|
+
**原始碼**:
|
|
939
|
+
```ts
|
|
940
|
+
export type ITSValueOf<T> = T[keyof T];
|
|
941
|
+
export type ITSValueOfArray<T extends readonly any[]> = ITSValueOf<T>;
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
**範例**:
|
|
945
|
+
```ts
|
|
946
|
+
type Arr = string[];
|
|
947
|
+
type Element = ITSValueOfArray<Arr>;
|
|
948
|
+
// 輸出結果:type Element = string
|
|
949
|
+
|
|
950
|
+
type Arr2 = [string, number, boolean];
|
|
951
|
+
type Element2 = ITSValueOfArray<Arr2>;
|
|
952
|
+
// 輸出結果:type Element2 = string | number | boolean
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
---
|
|
956
|
+
|
|
957
|
+
### ITSToReadonlyArray
|
|
958
|
+
|
|
959
|
+
- **位置**: `lib/helper/array/readonly.ts`
|
|
960
|
+
- **功能**: 將可寫陣列轉為唯讀陣列
|
|
961
|
+
|
|
962
|
+
**原始碼**:
|
|
963
|
+
```ts
|
|
964
|
+
export type ITSToReadonlyArray<T extends any[]> = T & readonly any[];
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
**範例**:
|
|
968
|
+
```ts
|
|
969
|
+
type Arr = string[];
|
|
970
|
+
type ReadonlyArr = ITSToReadonlyArray<Arr>;
|
|
971
|
+
// 輸出結果:type ReadonlyArr = readonly string[]
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
---
|
|
975
|
+
|
|
976
|
+
### ITSToWriteableArray
|
|
977
|
+
|
|
978
|
+
- **位置**: `lib/helper/array/readonly.ts`
|
|
979
|
+
- **功能**: 將唯讀陣列轉為可寫陣列
|
|
980
|
+
|
|
981
|
+
**原始碼**:
|
|
982
|
+
```ts
|
|
983
|
+
export type ITSToWriteableArray<T extends readonly any[]> = T extends readonly (infer U)[] ? U[] : never;
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
**範例**:
|
|
987
|
+
```ts
|
|
988
|
+
type Arr = readonly string[];
|
|
989
|
+
type WritableArr = ITSToWriteableArray<Arr>;
|
|
990
|
+
// 輸出結果:type WritableArr = string[]
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
---
|
|
994
|
+
|
|
995
|
+
## 13. 字串類型 / String Types
|
|
996
|
+
|
|
997
|
+
### ITSToStringLiteral
|
|
998
|
+
|
|
999
|
+
- **位置**: `lib/helper/string.ts`
|
|
1000
|
+
- **功能**: 將類型轉為字面量類型
|
|
1001
|
+
|
|
1002
|
+
**原始碼**:
|
|
1003
|
+
```ts
|
|
1004
|
+
export type ITSToStringLiteral<T> = string extends T ? string : T & string;
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
**範例**:
|
|
1008
|
+
```ts
|
|
1009
|
+
type Result = ITSToStringLiteral<123>;
|
|
1010
|
+
// 輸出結果:type Result = "123"
|
|
1011
|
+
|
|
1012
|
+
type Result2 = ITSToStringLiteral<'hello'>;
|
|
1013
|
+
// 輸出結果:type Result2 = "hello"
|
|
1014
|
+
|
|
1015
|
+
type Result3 = ITSToStringLiteral<string>;
|
|
1016
|
+
// 輸出結果:type Result3 = string
|
|
1017
|
+
```
|
|
1018
|
+
|
|
1019
|
+
---
|
|
1020
|
+
|
|
1021
|
+
### ITSCamelCase
|
|
1022
|
+
|
|
1023
|
+
- **位置**: `lib/helper/string/literal-string.ts`
|
|
1024
|
+
- **功能**: 轉為駝峰式命名
|
|
1025
|
+
|
|
1026
|
+
**原始碼**:
|
|
1027
|
+
```ts
|
|
1028
|
+
export type ITSCamelCase<S extends string> =
|
|
1029
|
+
string extends S ? string :
|
|
1030
|
+
S extends `${infer T}-${infer U}` ? `${T}${ITSPascalCase<U>}` : S;
|
|
1031
|
+
```
|
|
1032
|
+
|
|
1033
|
+
**範例**:
|
|
1034
|
+
```ts
|
|
1035
|
+
type Result = ITSCamelCase<'hello_world'>;
|
|
1036
|
+
// 輸出結果:type Result = "helloWorld"
|
|
1037
|
+
|
|
1038
|
+
type Result2 = ITSCamelCase<'hello-world'>;
|
|
1039
|
+
// 輸出結果:type Result2 = "helloWorld"
|
|
1040
|
+
```
|
|
1041
|
+
|
|
1042
|
+
---
|
|
1043
|
+
|
|
1044
|
+
### ITSPascalCase
|
|
1045
|
+
|
|
1046
|
+
- **位置**: `lib/helper/string/literal-string.ts`
|
|
1047
|
+
- **功能**: 轉為帕斯卡命名
|
|
1048
|
+
|
|
1049
|
+
**原始碼**:
|
|
1050
|
+
```ts
|
|
1051
|
+
export type ITSPascalCase<S extends string> =
|
|
1052
|
+
string extends S ? string :
|
|
1053
|
+
S extends `${infer T}-${infer U}` ? `${Capitalize<T>}${ITSPascalCase<U>}` : Capitalize<S>;
|
|
1054
|
+
```
|
|
1055
|
+
|
|
1056
|
+
**範例**:
|
|
1057
|
+
```ts
|
|
1058
|
+
type Result = ITSPascalCase<'hello_world'>;
|
|
1059
|
+
// 輸出結果:type Result = "HelloWorld"
|
|
1060
|
+
|
|
1061
|
+
type Result2 = ITSPascalCase<'hello-world'>;
|
|
1062
|
+
// 輸出結果:type Result2 = "HelloWorld"
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
---
|
|
1066
|
+
|
|
1067
|
+
## 14. Promise 類型 / Promise Types
|
|
1068
|
+
|
|
1069
|
+
### ITSAwaitedReturnType
|
|
1070
|
+
|
|
1071
|
+
- **位置**: `lib/helper/promise.ts`
|
|
1072
|
+
- **功能**: 解析 Promise 的返回類型
|
|
1073
|
+
|
|
1074
|
+
**原始碼**:
|
|
1075
|
+
```ts
|
|
1076
|
+
export type ITSAwaitedReturnType<T extends ITSAnyFunction> = ITSAwaitedLazy<ReturnType<T>>;
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
**範例**:
|
|
1080
|
+
```ts
|
|
1081
|
+
declare function fetch(): Promise<string>;
|
|
1082
|
+
type Result = ITSAwaitedReturnType<typeof fetch>;
|
|
1083
|
+
// 輸出結果:type Result = string
|
|
1084
|
+
|
|
1085
|
+
declare function fetch2(): Promise<Promise<number>>;
|
|
1086
|
+
type Result2 = ITSAwaitedReturnType<typeof fetch2>;
|
|
1087
|
+
// 輸出結果:type Result2 = number
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
---
|
|
1091
|
+
|
|
1092
|
+
### ITSDeferred
|
|
1093
|
+
|
|
1094
|
+
- **位置**: `lib/type/promise.ts`
|
|
1095
|
+
- **功能**: 延遲物件類型
|
|
1096
|
+
|
|
1097
|
+
**原始碼**:
|
|
1098
|
+
```ts
|
|
1099
|
+
export type ITSDeferred<T> = {
|
|
1100
|
+
promise: Promise<T>;
|
|
1101
|
+
resolve: (value: T | PromiseLike<T>) => void;
|
|
1102
|
+
reject: (reason?: any) => void;
|
|
1103
|
+
};
|
|
1104
|
+
```
|
|
1105
|
+
|
|
1106
|
+
**範例**:
|
|
1107
|
+
```ts
|
|
1108
|
+
type Def = ITSDeferred<string>;
|
|
1109
|
+
// 輸出結果:type Def = { promise: Promise<string>; resolve: (value: string) => void; reject: (reason?: any) => void; }
|
|
1110
|
+
```
|
|
1111
|
+
|
|
1112
|
+
---
|
|
1113
|
+
|
|
1114
|
+
## 15. 函數類型 / Function Types
|
|
1115
|
+
|
|
1116
|
+
### ITSOverwriteReturnType
|
|
1117
|
+
|
|
1118
|
+
- **位置**: `lib/helper.ts`
|
|
1119
|
+
- **功能**: 覆寫函數返回值類型
|
|
1120
|
+
|
|
1121
|
+
**原始碼**:
|
|
1122
|
+
```ts
|
|
1123
|
+
export type ITSOverwriteReturnType<T extends (...args: any[]) => any, R extends unknown> = (...args: Parameters<T>) => R;
|
|
1124
|
+
```
|
|
1125
|
+
|
|
1126
|
+
**範例**:
|
|
1127
|
+
```ts
|
|
1128
|
+
declare function f(a: number): number;
|
|
1129
|
+
type Result = ITSOverwriteReturnType<typeof f, string>;
|
|
1130
|
+
// 輸出結果:type Result = (a: number) => string
|
|
1131
|
+
```
|
|
1132
|
+
|
|
1133
|
+
---
|
|
1134
|
+
|
|
1135
|
+
### ITSUnionToIntersection
|
|
1136
|
+
|
|
1137
|
+
- **位置**: `lib/helper/intersection.ts`
|
|
1138
|
+
- **功能**: 將聯合類型轉為交集類型
|
|
1139
|
+
|
|
1140
|
+
**原始碼**:
|
|
1141
|
+
```ts
|
|
1142
|
+
export type ITSUnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1145
|
+
**範例**:
|
|
1146
|
+
```ts
|
|
1147
|
+
type Union = { a: string } | { b: number };
|
|
1148
|
+
type Intersection = ITSUnionToIntersection<Union>;
|
|
1149
|
+
// 輸出結果:type Intersection = { a: string } & { b: number }
|
|
1150
|
+
```
|