배열에서 shift()하는 방법(TS)

조민호·2023년 1월 25일
0
post-custom-banner


TS를 배우던 도중 갑자기 백준에서 알고리즘 문제도 TS로 풀리는지 알아보고 싶었다

백준은 TS컴파일러를 지원하지 않기에 TS로 작성하고 JS로 컴파일한 코드로 풀어보면 되겠지?

라는 생각으로 TS로 코드를 작성하는데,

나는 readline템플릿을 사용하고 있어서 백준에서 주어진 입력값을 빼오려면 shift()를 사용해야했다

근데 이 shift() 하는데만 정말 많은 에러를 쏟아냈고 해결하면서 역시 TS는 타입만 추가된 단순한 언어가 아닌 정말 정교한 언어라는 것을 다시 한번 깨달았다





배열을 사용할때 shfit()메소드를 사용할 때가 있습니다

여기서 반드시 수행해야 할 과정이 있습니다

  1. 배열에서 shift()를 해올때 무조건 값이 리턴된다는 보장이 없습니다. 만약 배열이 비어있다면 undefined가 리턴됩니다

    그러므로 리턴값을 받는 변수 또한 union type으로 undefined도 선언해 줘야 합니다

  2. shift()한 리턴값을 다른 타입으로 받는 것이라면

    shfit()한 리턴값에 대해서 반드시 타입을 즉시 캐스팅 해줘야 합니다.



let data: number[] = [1,2,3,4];

let N: number | undefined = data.shift();

// let N = data.shift();
// 이렇게 해도 에러는 안 뜨긴 하지만, 이 방식은 TS가 아니라 JS입니다
  • 배열에서 shift()를 해올때 무조건 값이 나온다는 보장이 없으므로 union type으로 undefined도 해줍니다


let data: string[] = ['5', '54321'];

let N: number | undefined = Number(data.shift());
  • 배열에서 shift()를 해올때 무조건 값이 나온다는 보장이 없으므로 union type으로 undefined도 해줍니다
  • data.shift()로 리턴한 값은 문자열이지만 N은 number입니다 그러므로 shfit()를 사용한 곳에 즉시 Number()로 타입을 캐스팅 해줍니다

    💡 TS에서는 앞에 +를 붙여서 숫자형으로 변환하는 방식이 불가능 한 것 같습니다



이 경우는 좀 특이합니다

let data2: string[] = ['54321'];

let numbers: number[] = String(data2.shift()).split('').map(Number);
  • string배열에서 shift()를 했는데 shift()의 리턴값에 대해서 String()으로 캐스팅을 하고 있습니다

    • shift()만 하는거면 String()으로 캐스팅을 안 해도 되지만
      뒤에 split(’’)이 있습니다

    • 만약 배열이 비어서 undefined가 리턴된다면 split(’’)을 사용할 수 없습니다 그래서 String으로 캐스팅을 진행해주면 undefined가 나온다 하더라도 ‘undefined'가 돼서 split(’’)이 가능하게 됩니다

      💡 이렇게 발생가능한 모든 에러를 막아줘야 TS에서 에러가 발생하지 않습니다

  • 그리고 numbers의 타입 또한 union type으로 undefined를 해주지 않습니다

    • 바로 위에서 언급했듯이 shift()에서 undefined가 나와도 String()으로 캐스팅을 해줘
      서 무조건 split(’’)이 가능합니다
      그리고 그 결과값에 대해서 map(Number)를 해주고 있으므로

    • String(data2.shift()).split('').map(Number)의 결괏값은 절대 undefined가 뜰리가 없게 됩니다

      💡 ‘undefined’에 대해서 map(Number) 를 해줘도 [ NaN, NaN, NaN, …] 으로 나오게 됩니다 그러므로 union type으로 undefined를 선언할 필요도 없습니다




그리고 또 하나의 방법이 있습니다

const data: string[] = ['54321'];

const tmp = (data: string[]): number[] | undefined => {
  const str = data.shift();
  if (!str) { //undefined라면 그냥 리턴
    return;
  }
  const numbers: number[] = str.split('').map(Number);
  return numbers;
};

let result = tmp(data);
if (result) {
  console.log(result); // [ 5, 4, 3, 2, 1 ]
} else {
  console.log(undefined);
}

['54321'] 을 숫자 배열로 리턴하는 과정에서 함수를 사용한 것입니다

  • data.shift()를 할때 함수 안에서 진행하며
  • data.shift()를 받는 str의 타입을 string | undefined로 하지 않고 우선 JS스럽게 받은 다음에
  • undefined일 경우, if문에서 따로 걸러냅니다

💡 함수 안에서 shift()의 리턴값을 바로 타입으로 검열하지 않고 우선 받은 다음, 조건부로 undefined를 리턴해주는 것입니다
  • 그리고 undefined가 아니라면 split(’’).map(Number)를 진행합니다 numbers의 변수도 이미 str은 undefined가 아닌 것이 보장됐으므로 타입으로 | undefined 를 해줄 필요가 없습니다
post-custom-banner

0개의 댓글