# TypeScript Utility Types
### 什麼是 Utility Types?
> TypeScript provides several utility types to facilitate common type transformations.
在程式中有時候會撰寫 utils function,透過封裝好的函式將 input 做了些處理並 output 回傳。
在 TS 中也有這些 Type 小工具可以使用,只是 input 為型別,利用這些工具達到「**依據原有的型別,創建新的型別**」。
## 常見的 Utility Types 用法
### 1. Partial
將類型 Type 中的所有屬性設置為 optional
```
interface User {
name: string;
age: number;
}
function updateUser(user: User, newUser: Partial<User>): void {
return [...user, ...newUser]
}
const user: User = { name: 'Nono', age: 30 };
updateUser(user, { name: 'Alice' });
```
### 2. Required
將所有 Type 中的屬性設置為必填,`Partial` 的相反用法
```
interface User {
name?: string;
age?: number;
}
const requiredUser: Required<User> = {
name: 'Nono',
// Property 'age' is missing in type '{ name: string; }' but required in type 'Required<User>'.(2741)
};
```
### 3. Readonly
使 Type 中的所有屬性變成唯讀特性,不能夠重新指向賦值
```
interface Config {
apiUrl: string;
}
function fetchConfig(): Readonly<Config> {
return {
apiUrl: 'https://api.example.com',
};
}
const config = fetchConfig();
config.apiUrl = 'https://example.com'
// Cannot assign to 'apiUrl' because it is a read-only property.(2540)
```
### 4. Record
`Record<Keys, Type>` 創建物件類型,其屬性 Key 值為 Keys,屬性 Value 為 Type。 此實用程式可用於將一種類型的屬性對應到另一種類型
```
type Fruit = 'apple' | 'banana' | 'orange';
type Price = number;
const fruitPrices: Record<Fruit, Price> = {
apple: 20,
banana: 10,
orange: 15
};
```
這邊可以看到前者的 Fruit 型別變成 key 值,後者 Price 型別則是 value 型別
### 5. Pick
`Pick<Type, Keys>` 從 Type 中**選擇**指定的屬性
```
interface User {
name: string;
age: number;
email: string;
}
type UserProfile = Pick<User, 'name' | 'email'>;
const userDetails: UserProfile = {
// 因為僅選擇 name 與 email,所以 age 沒有也可以定義。
name: 'Nono',
email: 'Nono@example.com'
};
```
### 6. Omit
`Omit<Type, Keys>`從 Type 中**剔除**指定的屬性
```
interface User {
name: string;
age: number;
email: string;
}
type UserProfile = Omit<User, 'email'>;
const userProfile: UserProfile = {
name: 'Nono',
age: 30
};
```
### 7. Exclude
`Exclude<UnionType, ExcludedMembers>`從 UnionTyp 中剔除可以指派的 union type (差集)
```
type Animal = 'dog' | 'cat' | 'bird' | 'fish';
type Pet = 'dog' | 'cat';
type WildAnimal = Exclude<Animal, Pet>;
// 從 Animal type 中排除 Pet,即非寵物的動物,WildAnimal 的Type將是 'bird' | 'fish'
```
### 8. Extract
`Extract<Type, Union>`從 UnionTyp 中提取可以指派的 union type (聯集)
```
type Animal = 'dog' | 'cat' | 'bird' | 'fish';
type Pet = 'dog' | 'cat';
type MyPet = Extract<Animal, Pet>; // 提取 Animal 中屬於 Pet 的部分,MyPet 的 Type 是 'dog' | 'cat'
```
### Refer:
https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeuniontype-excludedmembers