Typescript 숙제와 함께 익숙해지기 : part 1

동화·2023년 3월 20일
0

코딩애플

목록 보기
5/7
post-thumbnail

숙제

1

클리닝함수( ['1', 2, '3'] ) 이렇게 숫자와 문자가 섞인 array를 입력하면
[1,2,3] 이렇게 숫자로 깔끔하게 변환되어 나오는 클리닝함수를 만들어오고 타입지정

function 클리닝함수(x: (number | string)[]) {
  let 클리닝배열: number[] = [];

  if (typeof x === "string") {
    클리닝배열.push(parseInt("x"));
  } else {
    클리닝배열.push(x);
  }
}

내가 처음에 만들었던 함수는 이랬다.
근데 클리닝배열 변수를 숫자만 이루어진 배열로 지정해주고,
if문을 이용해 클리닝함수의 요소들을 하나씩 push 해주는 것.
(push : 배열에 요소 추가 / concat : 배열과 배열 합침 - 아니 이걸 누가 아직도 헷갈려서 써여? 나야나)

근데 else { 클리닝배열.push(x); } 에서 x에 오류가 났다

그러니까 x의 타입은 string 이거나 number 인데 지금 숫자만 들어있는 클리닝배열에 넣을 수 없어! 라는 말이다.

그래서 x의 타입을 assertion 문법으로 덮어씌워주면 되나...? 하고
else { 클리닝배열.push(x as number); }라고 바꿔봤는데 이번엔 다른 오류가 나왔다.

x를 다짜고짜 숫자로 바꾸려고 한 게 잘못이다.
바보같지만... x는 배열 내 숫자or문자가 아니라 그렇게 이루어진 배열이다..
그러니 number를 넣으면 , 아니 초반에는 숫자/문자로 이루어진 배열이라더니 이걸 어떻게 number로 뒤집어쓰란말임??? 이 되는 것..
그러니 x 배열의 요소 하나하나를 실행할 또다른 메소드가 필요할 것이다.
나는 forEach를 이용해 보았다.

최종

function 클리닝함수(x: (number | string)[]) {
  let 클리닝배열: number[] = [];

  x.forEach((a) => {
    if (typeof a === "string") {
      클리닝배열.push(parseInt("a"));
    } else {
      클리닝배열.push(a);
    }
  });
}







2

선생님이 가르치고 있는 여러 과목중 맨 뒤의 1개를 return 해주는 함수

일단 쌤들의 과목도 타입지정을 해줌

let 철수쌤: { subject: string } = { subject: "math" };
let 영희쌤: { subject: string[] } = { subject: ["science", "english"] };
let 민수쌤: { subject: string[] } = { subject: ["science", "art", "korean"] };

그리고 함수를 만들어 보았다.

function 마지막과목(x: { subject: string[] | string }) {
  if (Array.isArray(x.subject)) {
    return x.subject.pop();
  } else {
    return x.subject as string;
  }
}

많은 이가 알고 있듯 pop() 말고도 마지막 배열 요소를 가져오는 방법은 많다... pop()은 원래 배열을 건드리기 때문에 안 사용하는 것이 좋지만, 여기선 어차피 가져오기만 하면 될 거니깐 나는 pop을 씀

배열 자르기

막간 코너~😁

  1. x[x.length - 1] 요소의 제일 마지막 요소를 가지고 옴.
    x[index숫자~~] 를 넣으면 요소를 출력할 수 있는데, 그 숫자를 x의 길이 -1 을 하면 가장 마지막 요소를 가지고 올 수 있다
  2. x.slice(-1)[0] 사용하기. slice() 는 배열의 특정 구간을 자를 때 사용하는 함수다. slice(-1)은 배열의 마지막 Index에서, 배열의 마지막까지 범위에 해당하는 요소들을 잘라서 배열로 리턴하는 것이기 때문에 [0]으로 인덱스 지정을 해주어 배열의 마지막 요소만 가지고 올 수 있음.
  3. x.at() 으로 배열의 마지막 요소 접근하기. Array.at()이라는 새로운 함수가 있는데, at(-1)은 마지막에서 첫번째 요소에 접근하고, at(-2)는 마지막에서 두번째 요소에 접근한다. 근데 이건 신 문법이라 못 쓰는 곳도 많음.
  4. x.pop() 사용. Array.pop()은 배열에서 마지막 요소를 삭제하고, 그 값을 리턴한다. 그러니까 내가 위에서 이렇게 써버렸으니, 쌤들은 이제... 가르치는 과목을 잃었을 것임. ㅠㅠ 그래서 수정했다..(결론) js로 바꾸는 과정에서 자꾸 배열이 바뀌어 버림..

최종


let 철수쌤: { subject: string } = { subject: "math" };
let 영희쌤: { subject: string[] } = { subject: ["science", "english"] };
let 민수쌤: { subject: string[] } = { subject: ["science", "art", "korean"] };

function 마지막과목(x: { subject: string[] | string }) {
  if (Array.isArray(x.subject)) {
    return x.subject.slice(-1)[0];
  } else {
    return x.subject as string;
  }
}

type alias

타입을 변수로 지정해서 조금 깔끔하게 표현해보기

type SubjectType = { subject: string | string[] };
let 철수쌤: SubjectType = { subject: "math" };
let 영희쌤: SubjectType = { subject: ["science", "english"] };
let 민수쌤: SubjectType = { subject: ["science", "art", "korean"] };;

참고로 타입 변수명은 대문자로 시작하는 것이 국룰




아무튼 단축도 해봤고.. 이제 위에서 만든 함수를 콘솔에 찍어서 확인해 보면...

잘 불러오는 걸 알 수 있다.

근데 타입스크립트 콘솔로 어떻게 불러오냐??? 자바스크립트밖에 인식 못하잖아?

console.log 이렇게!

일단 tsc 를 터미널에 입력해서 js 파일로 바꿔준다.
지금 내 typescript 파일이름은 index.ts 임.

tsc index.ts

이렇게 해주면 어쩌고저쩌고 끝에 index.js가 만들어 진다.
그럼 html 파일하나 만들어서,

<script src="index.js"></script>

넣어주고, 실행시켜주면 됨.

근데 콘솔로그는 잘 찍히는데 또다른 에러가 생겼다.

변수 선언 에러

cannot redeclare block-scoped variable '~'

두 가지 방법이 있는데,

tsconfig.json 파일에 아래 내용을 추가하면 된다.

"compilerOptions": {
        "lib" : [ "ES2015"]
    },

혹은 빈 object를 export 해주면 된다

export {};

왜 이런 오류가 생기는고하니,

TLDR; TypeScript uses the DOM typings for the global execution environment. In your case there is a 'co' property on the global window object.

To solve this: Rename the variable, or Use TypeScript modules, and add an empty export{}: or Configure your compiler options by not adding DOM typings:

타입스크립트는 전역 환경에서 DOM 타이핑을 사용해서 이미 전역 변수로 선언되어 있을 수 있다.

이럴 때는 변수를 renaming 하거나 export{} 해서 전역 환경과 분리하거나 혹은 컴파일러 옵션을 변경해 DOM typing을 제거하는 방법으로 해결할 수 있다. (위 json파일 수정)

참고 : https://web.archive.org/web/20180609155906/http://fullstack-developer.academy/cannot-redeclare-block-scoped-variable-name/







타입스크립트로 html 조작하기

일단 strictNullCheck 옵션을 준다.
많은 환경에서 null이 들어올 경우 체크해주는 옵션을 켜고 코드를 짜는데, 이유는 변수 조작하기 전에 이게 null인지 아닌지 캐치해낼 수 있기 때문이다.
특히 html 조작할 때 셀렉터로 찾으면 null 어쩌구가 많이 발생하는데 그거 잡을 때도 도움이 된다고.
어떻게 쓰냐면
아까 그 json 파일 컴파일러에 "strictNullChecks": true를 추가해주면 됨!

3

버튼을 누르면 이미지를 바꾸는 작업

<img id="image" src="test.jpg">

html 안에 이런 태그가 있다.
이걸 바꾸려면,

let 이미지 = document.querySelector("#image");
이미지.src = "new.jpg";

이렇게 해주면 된다.
근데 이렇게 하면 오류가 뜸. 왜냐면 우리가 위에서 strictNullChecks 옵션을 켜주었기 때문에
이거 Null 일 수도 있어~ 하고 알려준다
따라서 type narrowing을 해줌

let 이미지 = document.querySelector('#image');
if (이미지 instanceof HTMLImageElement){
  이미지.src = 'new.jpg';
}

4

다양한 링크의 주소를 바꾸는 방법

<a class="naver" href="naver.com">링크</a>
<a class="naver" href="naver.com">링크</a>
<a class="naver" href="naver.com">링크</a> 

의 주소를 모두 카카오로 바꿔본다.

let 링크 = document.querySelectorAll(".naver");
링크.forEach((a) => {
  if (a instanceof HTMLAnchorElement) {
    a.href = "https://kakao.com";
  }
});

forEach를 사용해서 풀었지만 map을 사용해서도 가능했다.

let 링크 = document.querySelectorAll(".naver");
let 링크배열 = Array.from(링크);
링크배열.map((a) => {
  if (a instanceof HTMLAnchorElement) {
    a.href = "https://kakao.com";
  }
});

Array.from에 대한 정보

반복문을 사용할 경우

let 링크 = document.querySelectorAll(".naver");

for (let i = 0; i < 3; i++) {
  let a = 링크[i];
  if (a instanceof HTMLAnchorElement) {
    a.href = "https://kakao.com";
  }
}

for문을 이용할 경우엔 변수를 만들ㄹ어줘야 매끄러운 narrowing이 가능하다.

querySelector와 getElementById

3번 문제에서 사용한 querySelector는 , class 모두 접근 가능하다.
하지만 getElementBy~~ 는 ~~ 부분에 들어오는 선택자만 접근할 수 있다
getElementById는 id만 불러올 수 있는 것이다.

위의 4 번문제를 풀었을 때, querySelector를 이용하면 NodeList로 출력이 된다.
그래서 여러 개의 요소를 선택하게 되면, index 값으로 접근이 가능하다.
getElementsByClassNameHTMLCollection을 출력한다.
HTMLCollectionquerySelector와 다르게 name, id, index번호로 접근 가능하기 때문에 처리속도에서 훨 좋다.

자세한 정보는 여기에 필요한 정보가 잘 담겨있음..

3 (getElementById)

let 이미지 = document.getElementById("#image");
if (이미지 instanceof HTMLImageElement) {
  이미지.src = "change.jpg";
}

4 (getElementsByClassName)

3번은 간단하게 변경이 되지만 여러개를 불러온 class는 다르다.

let 링크 = document.getElementsByClassName("naver");
링크.forEach((a) => {
  if (a instanceof HTMLAnchorElement) {
    a.href = "https://kakao.com";
  }
});

이렇게 변경하면 오류가 뜸.

위에서 한 말대로 getElementsByClassName 로 가져온 값은 prototype이 HTMLCollection이다.

⚡️ forEach는 array 배열만 사용 가능하다.

그렇기 때문에 forEach는 사용하지 못하고,
위에서 사용한 반복문을 이용해주면 된다.

let 링크 = document.getElementsByClassName("naver");

for (let i = 0; i < 3; i++) {
  let a = 링크[i];
  if (a instanceof HTMLAnchorElement) {
    a.href = "https://kakao.com";
  }
}

아니면 HTMLCollection으로 가져온 값을 배열로 바꿔줄 수도 있음.

let 링크 = document.getElementsByClassName("naver");
Array.from(링크).forEach((a) => {
  if (a instanceof HTMLAnchorElement) {
    a.href = "https://kakao.com";
  }
});

Array.from(링크).forEach((a)~~~~~ 사용해준 모습..!








5

Car 클래스를 만들기

  • { model : '소나타', price : 3000 } 이렇게 생긴 object를 복사해주는 class를 만들어 본다.
  • 복사된 object 자료들은 .tax() 라는 함수를 사용가능한데
    현재 object에 저장된 price의 10분의 1을 출력
class Car {
  model;
  price;

  constructor(a, b) {
    this.model = a;
    this.price = b;
  }

  tax() {
    return this.price * 0.1;
  }
}

let car1 = new Car("소나타", 3000);

이렇게 만들어주고, 이제 타입지정까지 해주면 완료

최종

class Car {
  model: string;
  price: number;

  constructor(a: string, b: number) {
    this.model = a;
    this.price = b;
  }

  tax() {
    return this.price * 0.1;
  }
}

let car1 = new Car("소나타", 3000);

콘솔에 찍어서 확인해주면,

console.log(car1);
console.log(car1.tax());

쉽게 완성시킬 수 있다.








6

파라미터가 잔뜩 들어가는 class Word

  1. object 만들 때 new Word() 소괄호 안에 숫자 혹은 문자를 입력
  2. 숫자는 전부 object 안의 num 속성 안에 array 형태로 저장,
  3. 문자는 전부 object 안의 str 속성 안에 array 형태로 저장되는 class 만들기
  4. class 만들 때 넣을 수 있는 숫자와 문자 갯수는 일단 제한X

최종

class Word {
  num: number[];
  str: string[];

  constructor(...param) {
    let nums: number[] = [];
    let strs: string[] = [];

    param.forEach((a) => {
      if (typeof a === "string") {
        strs.push(a);
      } else {
        nums.push(a);
      }
    });
    this.num = nums;
    this.str = strs;
  }
}

let obj = new Word("kim", 3, 5, "park");

num, str을 콘솔로그에 찍어보면,

아주 잘 출력되고 있음.!

클래스 낯설어.. ㅎ_ㅎ








7

object 안에 함수를 2개 넣기 (interface 이용)

  1. 이 object 자료는 plus() 함수를 내부에 가지고 있으며 plus 함수는 파라미터 2개를 입력하면 더해서 return
  2. 이 object 자료는 minus() 함수를 내부에 가지고 있으며 minus 함수는 파라미터 2개를 입력하면 빼서 return
let 덧셈뺄셈 = {
    plus(a,b) {return a+b},
    minus(a,b) {return a-b}
}

일단 대충 내부에 들어있는 함수부터 만들어 줌..

그리고 타입지정!
함수 타입 지정은 : () => 해주면 됨

interface Math {
    plus : (a: number,b:number) => number,
    minus: (a:number,b:number) => number
}

최종

interface Math {
  plus: (a: number, b: number) => number;
  minus: (a: number, b: number) => number;
}

let 덧셈뺄셈: Math = {
  plus(a, b) {
    return a + b;
  },
  minus(a, b) {
    return a - b;
  },
};

확인은 덧셈뺄셈.plus(1,3) 등으로 해주면 됨





파트1은 너무 쉬웠고... 그래서 재미있었지만..
(왠지 자바스크립트 처음 배울 때 기분ㅋㅋㅋㅋㅋㅋㅋ )
파트2는 어려울 거 같아서 조금 쫄린다 ㅠ.ㅠ 그래도 얼른 하고 싶어~
파이팅!

6개의 댓글

comment-user-thumbnail
2023년 3월 20일

초보자 맞춤형인거 같아요 잘보고갑니다!

답글 달기
comment-user-thumbnail
2023년 3월 21일

복습하기 좋네요 ~~ 잘 보고 갑니동

답글 달기
comment-user-thumbnail
2023년 3월 26일

제 맞춤형인거 같아요.. 잘 읽구 갑니다 총총총

답글 달기
comment-user-thumbnail
2023년 3월 26일

완벽한 정리네요 !!

답글 달기
comment-user-thumbnail
2023년 3월 26일

TS 보다 DOM 조작한거 보고 복습하고 갑니다 ㅋㅋㅋ 2탄에선 다양한 TS 활용법에 대해 보고싶네용

답글 달기
comment-user-thumbnail
2023년 3월 26일

덕분에 애플 강의 덩달아 듣는 느낌인걸요! 감사합니다 ㅎㅎ

답글 달기