Jieunny의 블로그

TypeScript 본문

React/etc

TypeScript

Jieunny 2021. 12. 18. 21:46
  • TypeScript : 자바스크립트에 타입을 부여한 언어로 자바스크립트의 확장된 언어라고 볼 수 있다.
  • '정적타입을 지원한다' - 변수나 데이터의 종류를 명확히 지정
  • 정적 타이핑
  • function sum(a: number, b: number) {	//타입을 미리 설정할 수 있음
      return a + b;
    }
  • const message : string = 'hello world'   //해당 상수 값이 문자열이라는 것을 명시 -> 해당 값을 숫자로 설정해버리면 오류가 나타난다.
  • 우리가 사전에 지정한 타입이 아닌 값이 설정될 때 바로 에러를 발생시킨다 -> 에러가 나타났을 땐 컴파일이 되지 않는다.
  • function sum(x: number, y: number): number {  //x,y 값이 number, sum 결과 값도 number 라는 뜻
      return x + y;
    }
    
    sum(1, 2);  //에러안남
    sum();  //에러남
  • interface
    • 클래스에서 interface를 implements 하기 
      • interface : 클래스 또는 객체를 위한 타입을 지정할 때 사용되는 문법
      • interface 를 사용하여 클래스가 가지고 있어야 할 요구사항 설정
      • 클래스 선언 시 implements 를 사용하여 해당 클래스가 특정 interface 를 구현한다는 것을 명시
      • interface Shape {
          getArea(): number; // Shape interface 에는 getArea 라는 함수가 꼭 있어야 하며 해당 함수의 반환값은 숫자
        }
        
        class Circle implements Shape {
          // `implements` 키워드를 사용하여 해당 클래스가 Shape interface 의 조건을 충족하겠다는 것을 명시
          constructor(public radius: number) {
            this.radius = radius;
          }
    • 일반 객체를 interface 로 타입 설정하기
      • interface Person {
          name: string;
          age?: number; // 물음표가 들어갔다는 것은, 설정을 해도 되고 안해도 되는 값이라는 것을 의미
        }
        interface Developer extends Person {  // Person interface를 상속받음
          skills: string[];
        }
        
        const person: Person = {
          name: '김사람',
          age: 20
        };
    • Type Alias 사용하기
      • 특정 타입에 별칭을 붙이는 용도
      • 객체, 배열 어떤 타입이던 별칭을 지어줄 수 있다.
      • type People = Person[];	//Person[]을 앞으로 People 이라는 타입으로 사용 할 수 있다
    • 함수에서 Generics 사용하기
      • Generics : 여러 종류의 타입에 대하여 호환을 맞춰야 하는 상황에서 사용하는 문법.
      • 어떤 타입이 올 지 모르는 상황에서 사용할 때 타입이 깨지지 않게 함.
      • function wrap<T>(param: T) {
          return {
            param	//param: number; 와 같음
          }
        }
        
        const wrapped = wrap(10);
      • <T> 처럼 '<>' 안에 타입의 이름을 넣어서 사용
    • interface에서 Generics 사용하기
      • interface Items<T> {
          list: T[];
        }
        
        const items: Items<string> = {
          list: ['a', 'b', 'c']
        };
      • Items<string> 라는 타입을 사용하게 되면, Items 를 지니고 있는 객체 list 배열은 string[] 타입을 지니고 있게 된다.
    • Type alias 에서 Generics 사용하기
      • type Items<T> = {
          list: T[];
        };
        
        const items: Items<string> = {
          list: ['a', 'b', 'c']
        };


  • Map을 사용하는 방법
    • Map: Key를 이용하여 Value를 저장하는 방식의 자료구조
    • Key는 중복될 수 없고 중복될 경우, 가장 마지막 value가 저장된다.
    • 선언
      • const map = new Map();
        const mapWithType = new Map<string, any[]>();
    • 데이터 저장
      • set(key, value) 를 이용해 key와 value를 저장한다.
      • const map = new Map<string, string[]>();
        map.set('key1', ['value1', 'value2']);
        map.set('key2', ['value1', 'value2', 'value3']);
        map.set('key3', ['value1', 'value2', 'value3', 'value4']);
        
        map.set('key2', ['value1']);	//	key가 중복될 경우, 가장 마지막 value가 저장되기 때문에 특정 key의 value를 업데이트 할 때 사용된다.
    • 데이터 삭제
      • delete(key) 사용
      • map.delete('key2');		// 가능
        map.delete('key4');		// key 값이 key4인 데이터가 없으므로 불가능
      • clear() 사용해서 모든 데이터 삭제 가능
    • 데이터 조회
      • get(key) 사용
      • map.get('key1');	// value1, value2
        map.get('key4');	// undefined
    • 데이터 존재 여부 확인
      • has(key) 사용
      • map.has('key1');	// true
        map.has('key4');	// false
    • key or value 값을 리스트 형태로 구하기
      • keys(), values() 사용 
      • const mapKeys = map.keys();
        for (const key of mapKeys) {
          ${key}
        }	//	key1, key2, key3
    • 반복문
      • for ... of
      • const map = new Map<string, string[]>();
            map.set('keyOne', ['value1', 'value2']);
            map.set('keyTwo', ['value1', 'value2', 'value3']);
            map.set('keyThree', ['value1', 'value2', 'valu3', 'value4']);
        
            for (const [key, values] of map) {
                console.log(`KEY: ${key}, VALUE: ${values}`);
            }
        
        //   KEY: keyOne,   VALUE: value1,value2
        //   KEY: keyTwo,   VALUE: value1,value2,value3
        //   KEY: keyThree, VALUE: value1,value2,valu3,value4
      • forEach
        • value, key, Object 순서
        • key, value의 위치에 주의해야한다.
        • const map = new Map<string, string[]>();
              map.set('keyOne', ['value1', 'value2']);
              map.set('keyTwo', ['value1', 'value2', 'value3']);
              map.set('keyThree', ['value1', 'value2', 'valu3', 'value4']);
          
              // obj === map
              map.forEach((values, key, obj) => {
                  console.log(`KEY: ${key}, VALUE: ${values}`);
              });
              
              // KEY: keyOne,   VALUE: value1,value2
              // KEY: keyTwo,   VALUE: value1,value2,value3
              // KEY: keyThree, VALUE: value1,value2,valu3,value4
        • Type Alias vs Interface
          • 둘다 비슷한 방식으로 이름을 지어줄 수 있다.
          • //interface
            
            interface Human {
              name: string;
              age: number;
            }
            
            const jieun: Human = {
              name: '김지은',
              age: 23
            };
            
            //Type Alias
            
            type Human = {
              name: string;
              age: number;
            };
            
            const jieun: Human = {
              name: '남현욱',
              age: 20,
            };
          • Interface는 선언 병합이 가능하지만, Type Alias 는 불가능 하다.
            • 선언 병합 : 동일한 이름으로 여러 번 선언해도 컴파일 시점에 합칠 수 있다.

 

  • TypeScript로 리액트 Hooks 사용하기
    • 1) useState
      • 제네릭 <number>을 통해 해당 state가 어떤 타입을 가지고 있는지 설정한다.
      • import React, { useState } from 'react';
        
        function Counter(){
            const [count, setCount] = useState<number>(0);	// count 값이 number 라는 것을 명시
            const onIncrease = () => { setCount(count + 1); }
            const onDecrease = () => { setCount(count - 1); }
            return (
              <div>
                <h1>{count}</h1>
                <div>
                  <button onClick={onIncrease}>+1</button>
                  <button onClick={onDecrease}>-1</button>
                </div>
              </div>
            );
        }
      • 제네릭을 사용하지 않아도 자동으로 유추하는데 왜 사용하나?
        • 1) state가 null일 수도 있고 아닐수도 있을때 유용하다.
        • type Information = { name: string; description: string };
          const [info, setInformation] = useState<Information | null>(null);
        • 2) state의 타입이 까다로운 구조를 가진 객체이거나 배열일 때는 명시하는 것이 좋다.
        • type Todo = { id: number; text: string; done: boolean };
          const [todos, setTodos] = useState<Todo[]>([]);
      • useRef : 인자로 넘어온 초깃값을 useRef 객체의 .current 프로퍼티에 저장한다. 이 current 속성은 값을 변경해도 상태를 변경할 때 처럼 React 컴포넌트가 다시 렌더링 되지 않는다. React 컴포넌트가 다시 렌더링될 때도 마찬가지로 current 속성의 값이 유실되지 않는다.
      • 정의 3개
        • 1. useRef<T>(initialValue: T): MutableRefObject<T> 
          • 인자의 타입과 제네릭의 타입이 T로 일치하는 경우, MutableRefObject<T>를 반환한다.
          • MutableRefObject<T>의 경우 current 프로퍼티 그 자체를 직접 변경할 수 있다.
        • 2. useRef<T>(initialValue: T|null): RefObject<T>
          • 인자의 타입이 null을 허용하는 경우, RefObject<T>를 반환한다.
          • RefObject<T>는 current 프로퍼티를 직접 수정할 수 없다.
        • 3. useRef<T = undefined>(): MutableRefObject<T | undefined> 
          • 제네릭의 타입이 undefined인 경우 MutableRefObject<T | undefined>를 반환한다.
        • import React, { useRef } from 'react';
          
          const App = () => {
            const localVarRef = useRef<number>(0);	// useRef를 로컬변수로 사용하는 경우
            
            const handleButtonClick = () => {
              if (localVarRef.current) {
                localVarRef.current += 1;		// 버튼을 클릭할 때 마다 localValRef.current 값이 1씩 증가
                console.log(localVarRef.current);
              }
            };
            
            //	.current를 직접 수정할 수 있는 이유: useRef에 제네릭타입과 동일한 타입의 초기 인자를 줬으므로 1번 케이스.
            // 	때문에 localVarRef 는 MutableRefObject<number> 타입이고, .current를 직접 수정 가능, 로컬 변수처럼 사용할 수 있다.
            
            return (
              <div className="App">
                <button onClick={handleButtonClick}>+1</button>
              <div>
            );
          };
          
          export default App;
        • 만약 useRef에 인자를 null로 초기화 했다면?
        • ...
            const localValRef = useRef<number>(null);		// null로 초기화
            
            // null로 초기화하는 건 2번 경우, .current가 readonly인 RefObject를 반환하므로 직접 수정 못함.
            
            const handleButtonClick = () => {
              localValRef.current += 1;
              console.log(localVarRef.current);
            };
          ...
          
          // current 프로퍼티만 읽기 전용이고 current 프로퍼티의 하위 프로퍼티인 value는 여전히 수정 가능하다.
          // localValRef.current.value 는 수정 가능하다.


        • 로컬 변수 용도로 useRef를 사용하는 경우, MutableRefObject<T>를 활용
        • DOM을 직접 조작하기 위해 프로퍼티로 useRef를 사용하는 경우, RefObject<T>를 사용해야 하므로 초깃값을 null로 해주자.

 

'React > etc' 카테고리의 다른 글

CSS 속성 선언 순서  (0) 2021.12.26
CRA 없이 React 환경 구축  (0) 2021.12.19
styled-component  (0) 2021.12.17
<usum> main.css (에어비엔비 convention)  (0) 2021.12.17
SASS  (0) 2021.12.17