# Composing Types
###### tags: `Javascript, React, Typescript`
ref: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html#composing-types
## Unions
unions 的使用情境像是下方的字串或是字串的形式
```typescript=
type WindowStates = "open" | "closed" | "minimized";
type LockStates = "locked" | "unlocked";
type PositiveOddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
```
或是使用在 function 中的參數,可以帶入字串或是字串陣列
```typescript=
function getLength(obj: string | string[]) {
return obj.length;
}
```
甚至可以透過 typeof 來判斷參數的型別決定之後的動作
```typescript=
function wrapInArray(obj: string | string[]) {
if (typeof obj === "string") {
return [obj];
(parameter) obj: string
}
return obj;
}
```
## Generics
ref: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html#generics
Generics 提供 types 變數做操作,從下方範例可以看到是一個 <> 包裹做為變數,讓 Array 型別有更多的延伸操作
```typescript=
type StringArray = Array<string>;
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>;
```
下方範例可以看到,Type 的部分就是這邊的 Generics 並且全部帶入 string
```typescript=
interface Backpack<Type> {
add: (obj: Type) => void;
get: () => Type;
}
// This line is a shortcut to tell TypeScript there is a
// constant called `backpack`, and to not worry about where it came from.
declare const backpack: Backpack<string>; //這邊把 Type 帶入 string
// object is a string, because we declared it above as the variable part of Backpack.
const object = backpack.get();
// Since the backpack variable is a string, you can't pass a number to the add function.
backpack.add(23);
Argument of type 'number' is not assignable to parameter of type 'string'.
```
## Structural Type System
又稱作 duck typing 因為可以省略一些 type 的撰寫,當兩個物件有同樣的 value type 時,就會被視為同一個 type 因此可以忽略不寫
```typescript=
interface Point {
x: number;
y: number;
}
function logPoint(p: Point) {
console.log(`${p.x}, ${p.y}`);
}
// logs "12, 26"
const point = { x: 12, y: 26 };
logPoint(point);
```
甚至只有有 子集 有符合,多一點屬性也可以被接受,但如果完全對不上則不符合
```typescript=
const point3 = { x: 12, y: 26, z: 89 };
logPoint(point3); // logs "12, 26"
const rect = { x: 33, y: 3, width: 30, height: 80 }; // x, y 有符合即可被接受
logPoint(rect); // logs "33, 3"
const color = { hex: "#187ABF" }; // 屬性對不上
logPoint(color);
Argument of type '{ hex: string; }' is not assignable to parameter of type 'Point'.
Type '{ hex: string; }' is missing the following properties from type 'Point': x, y
```
只要其屬性是一樣的,在 class 上的行為也是一樣可以被接受
```typescript=
class VirtualPoint {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
const newVPoint = new VirtualPoint(13, 56);
logPoint(newVPoint); // logs "13, 56"
```