TypeScript 강의 정리: 데이터 타입

zeroequaltwo·2022년 9월 16일
0

TS

목록 보기
2/8

1. TS 주요 데이터 타입

: number(실수), string, boolean, object, array, tuple, enum(열거형), any 등

  • tuple 같은 경우는 python 같은 언어에서는 있는 데이터 형태이지만 JS에는 기본적으로 내재되어 있지 않은 데이터 타입이다. TS는 tuple 데이터 타입 또한 사용할 수 있게 해준다.
  • tuple이란 길이와 데이터 타입이 정해져서 그 형식을 벗어날 수 없는 배열이다.
  • tuple도 push는 할 수 있다. 나머지는 거의 안된다고 보면 된다.
  • enum은 서로 관련된 상수들을 편리하게 선언하기 위한 목적으로 만들어진 데이터 타입이다. 예를 들어 로그인 시 접속자의 역할을 코드화해서 관리할 경우, 일반 user는 100, 판매자는 200, amdin은 300이라고 쳤을 때 이를 편하게 후루룩 처리해버릴 수 있다.
  • any는 말그대로 어떤 데이터 타입이든 올 수 있다는 뜻이다. 따라서 유연성이 높지만 TS의 장점을 전혀 살리지 못하는 데이터 타입이다. 바닐라 JS와 다를 바 없기 때문이다.

2. 데이터 타입 명시법

var var1: number = 0;  // number
var var2: string = "예시";  //string
var var3: bolean = true;  //boolean
//object(객체 형식 명시시에는 반점(,)이 아닌 세미콜론(;)을 사용해야 한다)
var var4: {
	nickname: string;
    age: number;
} = {
	nickname: "0=2",
    age: 3700
}
//array
var var5: string[] = ["spring", "summer", "fall", "winter"];
var var6: any[] = ["Me", 3700, true];
//tuple
var var7: [string, number, boolean] = ["Me", 3700, true];
//enum
enum role {user=100, seller=200, admin=300};  //문자열 할당도 가능
enum role {user, seller, admin}; //-> 순서대로 0,1,2의 인덱스값을 부여받게 된다.
  • const(상수)로 선언된 변수에는 굳이 데이터 타입 명시 안해도 된다. 절대 변하지 않을 값이 때문이다. TS도 const로 선언된 변수는 데이터 타입을 추론하지 않고 그 자체를 고유값으로 여긴다.

3. 중첩된 데이터 타입 명시법

  • 예시 데이터:
const product = {
  id: 'abc1',
  price: 12.99,
  tags: ['great-offer', 'hot-and-new'],
  details: {
    title: 'Red Carpet',
    description: 'A great carpet - almost brand-new!'
  }
}
  • 데이터 타입 명시:
{
  id: string;
  price: number;
  tags: string[];
  details: {
    title: string;
    description: string;
  }
}

4. 유니언 타입

  • 유니언 타입은 여러개의 데이터 타입이 다뤄져야 할 때 사용하는 타입이다.
  • 유니언 타입을 쓸 때는 들어올 수 있는 데이터 타입을 '|'을 사용하여 나열하면 된다.
  • 다만 유니언 타입을 쓴다고 해서 TS가 들어온 모든 데이터 타입들을 알아서 추론하는 것은 아니다. 그저 여러 타입의 데이터가 들어올 수 있다는 것만 인식하고 있을 뿐이라서 아래와 같이 그냥 input1 + input2를 리턴해버리면 오류가 난다. 숫자만 들어올 거란 보장이 없는데 어떻게 무작정 더하냐고 앙탈(?)을 부리는 것이다. 따라서 넘버가 들어올 때와 아닌 데이터가 들어올 때를 구분해주는 로직이 추가로 들어가줘야 오류가 나지 않는다.
function combine(input1: number | string, input2: number | string){
  // return input1 + input2
  
  let result;
  if(typeof input1 === "number" && typeof input2 === "number"){
    result = input1 + input2;
  } else {
    result = input1.toString() + input2.toString();
  }
  return result;
}

const combinedAges = combine(30, 26);
console.log(combinedAges);  // 56

const combinedNames = combine("Anna", "Max");
console.log(combinedNames);  //AnnaMax

5. 리터럴 타입

  • 리터럴 타입은 기본 데이터 타입(number, string, boolean)을 바탕으로 사용자가 구체적인 데이터 값을 설정하는 것을 의미한다.
  • 아래의 코드처럼 resultConversion이라는 파라미터 값이 "as-number"나 "as-text"로 들어오지 않으면 오류가 난다. 어찌보면 enum과 비슷한 기능을 한다고 볼 수 있다.
  • 기능적 특성 때문에 유니언 타입과 함께 쓰여지는 것이 일반적이다.
function combine(input1: number | string, input2: number | string, resultConversion: "as-number" | "as-text"){
  
  let result;
  if(typeof input1 === "number" && typeof input2 === "number"){
    result = input1 + input2;
  } else {
    result = input1.toString() + input2.toString();
  }
  
  if(resultConversion === "as-number"){
    return +result;
  } else {
    return result.toString();
  }
}

const combinedAges = combine(30, 26, "as-number");
console.log(combinedAges);  // 56(number)

const combinedStringAges = combine("30", "26", "as-number");
console.log(combinedStringAges);  // 3026(number)

const combinedNames = combine("Anna", "Max", "as-text");
console.log(combinedNames); //AnnaMax(string)

6. 타입 앨리어스 / 사용자 앨리어스

  • 자주 사용하는 유니언/리터럴 타입의 경우 매번 똑같은 긴 값을 데려오는 게 귀찮을 것이다. 이때 type으로 타입 앨리어스를 선언하면 매번 불러올 필요없이 편하게 사용할 수 있다.
  • type은 TS에서만 제공하는 형태이다.
type combinable = number | string;  //타입 앨리어스
type conversionDescriptor = "as-number" | "as-text";  //사용자 앨리어스

function combine(input1: combinable, input2: combinable, resultConversion: conversionDescriptor){
  
  let result;
  if(typeof input1 === "number" && typeof input2 === "number"){
    result = input1 + input2;
  } else {
    result = input1.toString() + input2.toString();
  }
  
  if(resultConversion === "as-number"){
    return +result;
  } else {
    return result.toString();
  }
}

const combinedAges = combine(30, 26, "as-number");
console.log(combinedAges);  // 56(number)

const combinedStringAges = combine("30", "26", "as-number");
console.log(combinedStringAges);  // 3026(number)

const combinedNames = combine("Anna", "Max", "as-text");
console.log(combinedNames); //AnnaMax(string)
  • 객체에도 물론 적용 가능하다.
type User = { name: string; age: number };
const u1: User = { name: 'Max', age: 30 };

7. 반환타입

  • TS로 함수를 선언할 경우 파라미터뿐만 아니라 반환(return)값 또한 타입을 지정해놓을 수 있다. 파라미터 뒤에 ': type'을 입력하면 되고, 꼭 리턴값의 데이터 타입이 정해놓은 범위 안에서만 나와야 할 때 지정한다.
  • 아래와 같이 숫자와 숫자를 더하는 함수의 경우 당연히 리턴값도 숫자로 나올 것을 TS도 쉽게 추론할 수 있다. 따라서 이런 경우엔 굳이 리턴값의 타입을 지정해놓을 필요없다.
function add(n1: number, n2: number): number{
  return n1 + n2;
}
  • void: 함수가 아무것도 리턴하지 않을 때의 타입
  • JS에서 undefined는 존재하지 않는 '값'이지만 TS에서는 '타입'으로 사용한다.
  • void는 undefined를 포함한 값을 반환하지 않는 경우를 의미하고, undefined은 반환문이 있지만 값을 반환하지 않는 경우를 의미한다. 반환문을 써놓고 반환값이 없게 의도하는 경우는 드물기 때문에 보통은 반환값이 없을 경우 void로 지정해놓는다.
function printResult(num: number): void{
  console.log("result: " + num);
}

printResult(add(1,3));  // return 4
console.log(printResult(add(1,3)))  // undefined

function resUndefined: undefined{
  return;
}

8. 함수타입

  • 함수 또한 타입으로 지정할 수 있다. 하지만 TS가 함수에 파라미터가 몇 개인지까진 알 수 없기 때문에 매개변수가 있는 경우엔 화살표 함수(arrow function) 표기법과 유사하게 작성한다.
let combinedValues: Fuction;
combinedValues = add;
console.log(combinedValues(2,5));  // 7

combinedValues = printResult;
console.log(combinedValues(2,5));  // undefined -> 매개변수를 받지 못하는 함수이므로

let combinedValues = (a: numbr, b: number) => number;
combinedValues = add;
combinedValues = printResult;  // error! -> number 타입의 두 매개변수가 없고 number를 반환하지도 않기 때문에

9. 콜백

  • 함수타입과 크게 다르지 않다.
  • 아래는 콜백함수는 cb의 반환값을 void로 설정해놨는데 이 경우 콜백 안에 반환문을 넣어도 아무것도 반환되지 않는다.(이 경우 TS는 리턴문이 있다고 해서 문제삼지 않고 그저 리턴을 무시한다)
function addAndHandle(n1: number, n2: number, cb: (num: number) => void){
  const result = n1 + n2;
  cb(result);
}

addAndHandle(10, 20, (result) => {
  console.log(result);
  return result;  // no error but nothing returns;
})

10. unknown 타입

  • unknown은 any와 마찬가지로 사용자가 어떤 타입의 데이터를 입력할지 알 수 없는 상황에서 쓴다는 공통점이 있다. 하지만 any는 아예 데이터 타입 검사를 하지 않지만, unknown을 사용할 경우 타입을 좁혀서 사용해야 한다(데이터 타입을 지정해야 하는 순간엔 꼭 타입 검사를 한 번 하고 넘어간다).
  • any보다 안전하게 쓸 수 있으므로 any 쓸 자리를 대신하여 많이 쓴다.
let userInput: unknown;
let userName: string;

userInput = 5;  //OK
userInput = "Max";  //OK

userInput = userName;  // error
if(typeof userInput === "string"){  // OK
  userName = userInput;
}

11. never 타입

  • never는 항상 오류를 출력하거나 리턴 값을 절대로 내보내지 않음을 의미하는 타입으로, 보통 에러를 발생시키거나 무한 루프 함수의 return 값으로 사용한다.
  • nerver는 모든 타입의 하위타입이기 never type의 변수는 모든 type의 변수에 할당할 수 있다. 하지만 never type의 변수에는 never type을 제외한 any를 포함해 그 어떤 type의 변수도 할당할 수 없다.
function generateError(message: string, code: number): never{
  throw {message: message, errorCode: code};
}

generateError("An error occured!", 500);
profile
나로 인해 0=2가 성립한다.

0개의 댓글