# The Basic Cheatsheet

## 전제 조건

전제 조건을 보면서 알게 된 사실 정리

**TypeScript의 장점**

1. TypeScript를 쓴다면 JavaScript에서 unit test를 쓸 필요가 없다. TypeScript가 자동적으로 체크해 준다.
2. This is especially useful when you’re using a UI library and need to transform data. For example, if you’re using React, you’ll need to transform data in state updates.

**we can use mapped types like `Readonly` to convert one type to another type.**

```
   // Readonly<...> makes each property readonly
   type Todo = Readonly<{
     id: number
     text: string
     done: boolean
   }>

   // 위 <...>은 아래와 같다.
   type Todo = {
     readonly id: number
     readonly text: string
     readonly done: boolean
   }
```

`readonly`는 array의 push와도 같이 쓰일 수 있다.

**Type assertions**

```
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
```

```
// as Type을 더 추천한다.
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
```

출처 <https://ts.chibicode.com/todo/>

## Function Components

### Hooks

<https://github.com/DefinitelyTyped/DefinitelyTyped/blob/a05cc538a42243c632f054e42eab483ebf1560ab/types/react/index.d.ts#L800-L1031>

**useState**

```
const [user, setUser] = React.useState<IUser | null>(null);
```

default value인 null과 함께 `|`를 사용하는 `union type`을 많은 hook들은 사용한다.

**useRef**

initial value가 없는 ref container 생성할 때

```
const ref1 = useRef<HTMLElement>(null!);
const ref2 = useRef<HTMLElement | null>(null);
```

* **ref1**는 readonly용 react가 관리할  built-in ref attributes에 전달하기 위한 것? (Response handles for your current value setting)
* **ref2**는 `ref2.current`를 mutable하게 해주고 사용자가 직접관리하는 `instance variables` 를 위한 것이다.

네? 뭐라구여???

* [ ] 다시 공부할 필요 있음

**useEffect**

함수 또는 undefined 이외에 다른 것이 return 되지 않도록 주의한다.

`setTimeout`을 사용하는 경우 number가 return되기 때문에 curly brace로 꼭 감싸자.

**useRef**

```
function TextInputWithFocusButton() {
  // 초기값은 null, HTMLInputElement를 찾고 있다고 TypeScript에 말함
  const inputEl = React.useRef<HTMLInputElement>(null);
  const onButtonClick = () => {
    // strict null 체크는 inputEl와 current가 존재하는지 확인해야한다.
    // 존재하면 HTMLInputElement type이므로 따라서 method focus를 가진다. 🙂 Yay
    if (inputEl && inputEl.current) {
      inputEl.current.focus();
    }
  };
  return (
    <>
      {/* 또한 inputEl는 input요소만 사용할 수 있다? focus 때문인가 */}
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}
```

**useReducer**

reducer action을 [Discriminated Unions](https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions) 사용한다. return type을 정의하는 것을 절대 잊지말자.

```
type AppState = {};
type Action =
  | { type: "SET_ONE"; payload: string }
  | { type: "SET_TWO"; payload: number };

export function reducer(state: AppState, action: Action): AppState {
  switch (action.type) {
    case "SET_ONE":
      return {
        ...state,
        one: action.payload, // `payload` is string
      };
    case "SET_TWO":
      return {
        ...state,
        two: action.payload, // `payload` is number
      };
    default:
      return state;
  }
}
```

**Discriminated Unions(유니온 식별)**&#xC740; singleton types, union types, type guards, 및 type aliases을 결합하여 discriminated unions, tagged unions, 또는 algebraic(대수의) data type으로 불리는 고급 패턴을 빌드할 수 있다.

```typescript
interface Square {
  kind: "square";
  size: number;
}
interface Rectangle {
  kind: "rectangle";
  width: number;
  height: number;
}
interface Circle {
  kind: "circle";
  radius: number;
}
```

결합할 interface를 선언한다.

공통적으로 `kind`라는 프로퍼티를 가지고 있는데 이를 `discriminant` 혹은 `tag`라고 부른다.

```typescript
type Shape = Square | Rectangle | Circle;
```

결합쓰

```typescript
function area(s: Shape) {
    switch (s.kind) {
        case "square": return s.size * s.size;
        case "rectangle": return s.height * s.width;
        case "circle": return Math.PI * s.radius ** 2;
    }
}
```

discriminated union을 사용하자!

useReducer에서는 `type`이 `discriminant` 혹은 `tag`가 되는 것이고

이전에 봤던 코드들을 생각하면 App component에서 `status` 를 예시로 들 수 있을 거 같다.🤭

```
export interface VerifyingAuth {
  status: 'verifying';
}

export interface UnsignedAuth {
  status: 'unsigned';
  inProgress?: 'signing';
  error?: Error;
}

export interface SignedAuth {
  status: 'signed';
  inProgress?: 'passwordChanging' | 'unsigning';
  error?: Error;
  token: string;
  user: UserInfo;
}
```

```
export type Auth = VerifyingAuth | UnsignedAuth | SignedAuth;
```

```
<AuthProvider api={api}>
  {(auth: Auth) => {
    switch (auth.status) {
      case 'verifying':
        return <div>...verifying</div>;
      case 'unsigned':
        return (
          <Switch>
            <Route exact path="/" component={LoginPage} />
            <Redirect to="/" />
          </Switch>
        );
      case 'signed':
        return (
          <MissionProvider>
            <Switch>
              <Route path="/dashboard" component={DashboardPage} />
              <Route path="/missions/:missionId" component={MissionPage} />
              <Redirect to="/dashboard" />
            </Switch>
          </MissionProvider>
        );
      default:
        return <div>Unknown auth status...</div>;
    }
  }}
</AuthProvider>
```

**Custom Hooks**


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://seula00027.gitbook.io/til/typescript/react-typescript-cheatsheet-basic.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
