공청
개발하는 금융인
공청
전체 방문자
오늘
어제
  • 분류 전체보기 (102)
    • 개인적인 이야기 (27)
    • IT에 관한 글 (15)
    • 경제, 금융 (12)
    • Python (2)
    • Javascript (6)
    • golang (2)
    • 비전공자를 위한 IT 지식 (0)
    • SQL (SQLD,SQLP) (1)
    • React (Front-end) (29)
    • 정보처리기사 (0)
    • Typescript (4)
    • (study) 모던 자바스크립트 Deep Dive (0)

블로그 메뉴

  • 홈
  • 태그
  • 미디어로그
  • 방명록
  • 글쓰기

공지사항

인기 글

태그

  • approute
  • 언섹시비즈니스
  • react
  • 웹개발
  • 프로그래밍
  • 트래블카드
  • go
  • typescript
  • 기술스택
  • ChatGPT
  • react-router
  • 조건부렌더링
  • Effective Typescript
  • vite
  • WSGI
  • 미국주식
  • 일기
  • next.js
  • javascript
  • 짧은생각
  • HTTP
  • python
  • Golang
  • Fira Code
  • useref
  • 창업
  • 트래블월렛
  • 인터넷
  • vscode
  • sql

최근 댓글

최근 글

티스토리

반응형
공청

개발하는 금융인

3. 기본 변수들 타입스크립트로 타입 지정하기
카테고리 없음

3. 기본 변수들 타입스크립트로 타입 지정하기

2022. 12. 26. 15:43

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."

"블로그 내의 광고와 쿠팡 링크를 클릭해주시면 블로그 운영에 큰 힘이 됩니다."

반응형

 

1. 타입 지정하기

변수에 타입을 지정하기 위해서는 해당 변수에 어떤 타입이 담길지를 알아야 한다.

기존 코드에서 변수에 값을 가져오는 메서드에 마우스를 갖다대보자.

리턴값이 HTMLElement 혹은 null 이다.

가령 document.getElementById()를 보면 해당 아이디가 존재할 경우에는 HTMLElement를 가져올 것이고

그렇지 않으면 null값이 담길 것이다. (너무 당연한 것인데요?)

 

그래서 container 변수의 타입은 HTMLElement 혹은 null값을 담을 "유니온 타입"으로 지정해준다.

 

이런 식으로 하단의 변수를 모두 바꿔주면 다음과 같이 바꿀 수 있다.

 

 

 

2. 바꾼 코드

app.ts

type Store = {
  currentPage: number;
  feeds: NewsFeed[]; // NewsFeed라는 형태가 배열에 들어간다.
};

type NewsFeed = {
  id: number;
  comments_count: number;
  url: string;
  user: string;
  time_ago: string;
  points: number;
  title: string;
  read?: boolean; // 처음에 네트워크를 가져올 때는 없을 수 있는 값이므로 비어있을 수도 있다.
};

const container: HTMLElement | null = document.getElementById("root");
const ajax: XMLHttpRequest = new XMLHttpRequest();
const NEWS_URL = "https://api.hnpwa.com/v0/news/1.json";
const CONTENT_URL = "https://api.hnpwa.com/v0/item/@id.json";
const store: Store = {
  currentPage: 1, // 여기에 문자열을 넣으면 바로 오류를 뱉는다.
  feeds: [],
};

function getData(url) {
  ajax.open("GET", url, false);
  ajax.send();

  return JSON.parse(ajax.response);
}

function makeFeeds(feeds) {
  for (let i = 0; i < feeds.length; i++) {
    feeds[i].read = false;
  }

  return feeds;
}

function updateView(html) {
  if (container) {
    container.innerHTML = html;
  } else {
    console.error('최상위 컨테이너가 없어 UI를 진행하지 못합니다.');
  }
}

function newsFeed() {
  let newsFeed: NewsFeed[] = store.feeds;
  const newsList = [];
  let template = `
    <div class="bg-gray-600 min-h-screen">
      <div class="bg-white text-xl">
        <div class="mx-auto px-4">
          <div class="flex justify-between items-center py-6">
            <div class="flex justify-start">
              <h1 class="font-extrabold">Hacker News</h1>
            </div>
            <div class="items-center justify-end">
              <a href="#/page/{{__prev_page__}}" class="text-gray-500">
                Previous
              </a>
              <a href="#/page/{{__next_page__}}" class="text-gray-500 ml-4">
                Next
              </a>
            </div>
          </div> 
        </div>
      </div>
      <div class="p-4 text-2xl text-gray-700">
        {{__news_feed__}}        
      </div>
    </div>
  `;

  if (newsFeed.length === 0) {
    newsFeed = store.feeds = makeFeeds(getData(NEWS_URL));
  }

  for (let i = (store.currentPage - 1) * 10; i < store.currentPage * 10; i++) {
    newsList.push(`
      <div class="p-6 ${newsFeed[i].read ? "bg-red-500" : "bg-white"
      } mt-6 rounded-lg shadow-md transition-colors duration-500 hover:bg-green-100">
        <div class="flex">
          <div class="flex-auto">
            <a href="#/show/${newsFeed[i].id}">${newsFeed[i].title}</a>  
          </div>
          <div class="text-center text-sm">
            <div class="w-10 text-white bg-green-300 rounded-lg px-0 py-2">${newsFeed[i].comments_count
      }</div>
          </div>
        </div>
        <div class="flex mt-3">
          <div class="grid grid-cols-3 text-sm text-gray-500">
            <div><i class="fas fa-user mr-1"></i>${newsFeed[i].user}</div>
            <div><i class="fas fa-heart mr-1"></i>${newsFeed[i].points}</div>
            <div><i class="far fa-clock mr-1"></i>${newsFeed[i].time_ago}</div>
          </div>  
        </div>
      </div>    
    `);
  }

  template = template.replace("{{__news_feed__}}", newsList.join(""));
  template = template.replace(
    "{{__prev_page__}}",
    store.currentPage > 1 ? store.currentPage - 1 : 1
  );
  template = template.replace("{{__next_page__}}", store.currentPage + 1);

 updateView(template);
}

function newsDetail() {
  const id = location.hash.substr(7);
  const newsContent = getData(CONTENT_URL.replace("@id", id));
  let template = `
    <div class="bg-gray-600 min-h-screen pb-8">
      <div class="bg-white text-xl">
        <div class="mx-auto px-4">
          <div class="flex justify-between items-center py-6">
            <div class="flex justify-start">
              <h1 class="font-extrabold">Hacker News</h1>
            </div>
            <div class="items-center justify-end">
              <a href="#/page/${store.currentPage}" class="text-gray-500">
                <i class="fa fa-times"></i>
              </a>
            </div>
          </div>
        </div>
      </div>

      <div class="h-full border rounded-xl bg-white m-6 p-4 ">
        <h2>${newsContent.title}</h2>
        <div class="text-gray-400 h-20">
          ${newsContent.content}
        </div>

        {{__comments__}}

      </div>
    </div>
  `;

  for (let i = 0; i < store.feeds.length; i++) {
    if (store.feeds[i].id === Number(id)) {
      store.feeds[i].read = true;
      break;
    }
  }

  function makeComment(comments, called = 0) {
    const commentString = [];

    for (let i = 0; i < comments.length; i++) {
      commentString.push(`
        <div style="padding-left: ${called * 40}px;" class="mt-4">
          <div class="text-gray-400">
            <i class="fa fa-sort-up mr-2"></i>
            <strong>${comments[i].user}</strong> ${comments[i].time_ago}
          </div>
          <p class="text-gray-700">${comments[i].content}</p>
        </div>      
      `);

      if (comments[i].comments.length > 0) {
        commentString.push(makeComment(comments[i].comments, called + 1));
      }
    }

    return commentString.join("");
  }
  updateView(template.replace('{{__comments__}}', makeComment(newsContent.comments)));
}

function router() {
  const routePath = location.hash;

  if (routePath === "") {
    newsFeed();
  } else if (routePath.indexOf("#/page/") >= 0) {
    store.currentPage = Number(routePath.substr(7));
    newsFeed();
  } else {
    newsDetail();
  }
}

window.addEventListener("hashchange", router);

router();

 

여기서 눈에 띄는 것은 가장 위에 container 변수에 null이 들어갈 수 있다고 선언하는 순간

container 내부 변수 접근하는 코드들에 빨간색 줄이 그어진다.

 

null 값이 들어가면 해당 속성에 접근할 수 없기 때문에 그런 것인데,

이럴 때는 null이 아닐 때 처리를 해주어야 한다.

반응형
    공청
    공청
    투자, 프로그래밍, IT에 대한 글을 씁니다.

    티스토리툴바