---
# System prepended metadata

title: Composing Types
tags: ['Javascript, React, Typescript']

---

# 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"
```