Javascript/typescript

타입스크립트 빠르게 훑어보기 2 - type/interface

킹king 2023. 8. 25. 17:25
반응형

 

참고로 타입스크립트 뭔가 확확 변하는건지 2년전 다른 사람 포스팅에서 이건 안된다 했던거 지금 다 되서 당황함.

(해당 포스팅은 언제든지 내용 수정/추가 될 수 있음)

 

1. type

function log(user: {username: string, age: number, phone?: string, id: string, gender: string}) {
  console.log(user.username);
}

이 함수는 user라는 객체를 받아서 그 안에 있는 value를 알려주는데 이렇게 쓰면 너무 길어서 가독성 떨어짐.

 

type User = {
  username: string;
  age: number;
  phone?: string;
  readonly id: string; // 읽기 전용
  gender?: string;
};

function log(user: User) { // 함수에 들어갈 객체의 타입을 지정해주면 된다.
  console.log(user.username);
}

let me: User = { // 이렇게 객체에도 활용이 가능하다.
  username: "king",
  age: 23,
  id: "apple23"
};

me.username = "queen";
me.id = "iesjfs"; // error. 위에 읽기전용 key였기 때문에 수정 불가.

그럴때 바로 이렇게 나눠서 써줄 수 있음.

이제 어디에든 갖다 쓸 수 있음.

훌륭한 붕어빵틀 역할을 하고있음.

 

type Func = {
  (num1: number, num2?: number): number;
};

let add: Func = (x, y) => x + (y || 0); // y가 있으면 쓰고 없으면 기본값 0

이렇게 함수를 쓰는 것도 가능하다.

 

type User = {
  [key: string]: number
}

let me: User = {
  username: 3,
  age: 22,
  // 이후로 무한대로 작성 가능
}

이건 "key를 string으로 아무꺼나 쓰고, value는 number로 쓴다"라는 말이라 모든 형태가 저렇게 생겼다면 저렇게 일률적으로 정하는 것도 가능함(인덱스 시그니쳐).

 

이 기능에 대해서 좀 더 자세히 말해보자면, 해당 기능을 쓰지 않았을 때 아래와 같은 코드가 있을때 에러가 발생함(특히 반복문).

type spendList = {
    card: number;
    subway: number;
};

const moneyOut: spendList = { // 월급 퍼가요 리스트
    card: 467010,
    subway: 88200
};

function totalMoneyout(m: spendList): number { // 단순하게 지출값을 더해주는 함수
    let t = 0;
    for (const key in m) {
        t += m[key]; // error. key값이 'card', 'subway'인데 타입스크립트에서 string을 key로 인식하지 못하기 때문.
    }
    return t;
}

let k = "card";
console.log(moneyOut[k]); // error. 이것도 동일함.

이 경우 type spendList를 인덱스 시그니쳐 방법으로 써주면 문제가 사라짐.

type spendList = {
    [key: string]: number,
    card: number;
    subway: number;
};

또다른 방법으로는 as keyof를 써주면 된다.

// ...
t += m[key as keyof moneyOut];
// ...

만약에 key값을 함수 인자로 전달해야하는 방식이라면 이렇게 as빼고 keyof를 쓰면 된다.

function log(m: spendList, key: keyof spendList): void {
    console.log(`${key}: ${m[key]}`);
}

log(moneyOut, 'card'); // card: 467010

 

그리고 또하나 좋은 장점은 바로 이것만 써라 라고 하는걸 지정해줄 수 있다는 것임(리터럴 타입)

type User = {
  device: 'ios' | 'aos'
};

let me: User = {
  device: 'nothing phone' // error
}

이렇게 쓰면 ios, aos 둘 중 하나만 써야한다.

 

 

2. interface

type User = {
  name: 'king';
}

interface User {
  name: 'king';
}

생긴거 거의 똑같음.

역할도 똑같이 붕어빵틀2임.

위에 type이 이것도 되고 저것도 되고 하는거 다됨...

 

 

이쯤되면 어쩔티비같은데 그럼 도대체 차이점이 뭐냐라고 한다면 interface는 extends랑 같이 쓸 수 있음.

 

interface User {
  username: string;
  age: number;
}

interface employee extends User {
  team: string;
}

const me: employee = {
  username: 'king',
  age: 12,
  team: 'development'
}

어려운건 없고 그냥 기본으로 있는 user 설정값들 추가로 갖다쓸께요 하는게 extends임.

 

나중에 implement에서도 interface가 쓰임.

모든 게시물(특히 과거 게시물)은 잘못된 방법으로 처리한것을 좋다고 써놨을 수 있습니다. 참고만 하시고 틀린게 있다면 댓글 남겨주세요~