계발하는 개발자

[Typescript] 타입스크립트 타입 선언 & 종류 본문

📌 Language/Typescript

[Typescript] 타입스크립트 타입 선언 & 종류

dev_genie 2023. 10. 17. 02:29

타입스크립트를 공부하다보니 타입 지정할 때 여러모로 망설여지는 부분이 있어 이참에 공부할겸 정리!

 

먼저 타입스크립트의 기본 타입에는 다음의 12가지가 있다.

(그리고 여기서 더 나아가 이모저모 다양한 타입들이 있다..) 자주 쓰이는 위주로 정리해본다.

 

타입 - Boolean

타입이 진위 값인 경우에는 아래와 같이 선언한다.

let isCheck: boolean = false;

 

타입 - String

타입이 문자열인 경우 아래와 같이 선언한다.

작은따옴표('), 큰따옴표(") 뿐만 아니라 ES6의 템플릿 문자열도 string 타입에 포함된다.

let subTit: string = 'Hello';
let mTit: string = "World!";
let myName: string = 'my name is' + nora;
let myName: string = `My name is ${nora}.`;

function test(pm1: string, pm2: string): string {
	return pm1 + pm2;
}

 

타입 - Array

배열 타입은 두 가지 방법으로 쓸 수 있다.

첫 번째는 배열 요소들을 나타내는 타입 뒤에 []를 쓰는 방법,

두 번째는 Array<> 배열 타입을 쓰는 것이다.

// 배열 타입이 number인 경우
let arr: number[] = [1,2,3];
let arr: Array<number> = [1,2,3];

// 배열 타입이 string인 경우
let arr: string[] = ['one', 'two', 'three'];
let arr: Array<string> = ['one', 'two', 'three'];

// 배열 타입이 boolean인 경우
let bool:boolean[] = [true, false, true];

// 배열 타입이 모든 데이터 타입인 경우
let arr: any[] = [0, 1, {}, [], 'string', false];

// 배열 타입이 특정 데이터 타입인 경우
let matrial:(number | string)[] = [30, 'desk'];

 

타입 - Tuple

튜플은 배열 길이가 고정되고 각 요소의 타입이 지정되어 있는 배열 형식을 말한다.

let rgbColor: [number, number, number] = [255, 255, 0];
// or
let arr: [string, number] = ['hi', 10];

만약 정의하지 않은 타입, 인덱스로 접근할 경우 오류가 난다.

let elem: [string, number]; // 튜플 타입 선언

elem = ["hi", 5]; // 성공
elem = [7, "hi!"]; // 오류 (원소 타입 안맞음)
elem = ["hihi", 80, 30]; // 오류 (원소 갯수 안맞음)

타입 뿐만 아니라 값 자체를 고정시킬 수도 있다. (강한 타입)

/* 타입 뿐만 아니라 값 자체를 고정 */
let tuple: [1, number];
tuple = [1, 12];
tuple = [1, 7];

tuple = [2, 4]; // 오류 : Type '2' is not assignable to type '1'.

 

타입 - Enum

이넘은 C, Java와 같은 다른 언어에서 흔하게 쓰이는 타입으로 특정 값(상수)들의 집합을 말한다.

// 인덱스 번호로 접근 가능
enum Avengers { Captain, IronMan, Thor }
let hero: Avengers = Avengers[2]; //or Avengers.Thor

만약 원한다면 이넘의 인덱스를 사용자 편의로 변경하여 사용할 수도 있다.

enum Avengers { Captain = 3, IronMan, Thor }
let hero: Avengers = Avengers[3]; // Captain
let hero: Avengers = Avengers[5]; // Thor

 

타입 - Object

자바스크립트에서의 object는 객체 뿐만 아니라 배열, 함수 까지 object로 포함한다.

타입스크립트에서도 마찬가지라서 기본적으로 typeof 연산자가 "object"로 반환하는 모든 타입을 뜻한다.

let obj: object = {};
let arr: object = [];
let func: object = function () {};
let nullVal: object = null;
let newKeyword: object = new Date();

여러 타입의 상위 타입으로 인식되기 때문에 타입스크립트에서 object를 그대로 타입으로 쓰기에는 애로사항이 많다.

더군다나 다음과 같이 object 타입에 객체값을 주고 실제로 조회해 보면 에러가 나는 경우도 왕왕있다.

const user: object = { name: 'choco' };
user.name; // 오류 : "object 형식에 name 속성이 없습니다."

따라서 정말 객체에 타입을 지정해주고 싶다면 다음과 같이 객체 속성(Properties)들에 대한 타입을 개별적으로 지정하는 식으로 사용하면 된다.

let user1: { name: string, age: number };
userA = {
  name: 'happy',
  age: 23
};

let user2: { name: string, age: number };
userB = {
  name: 'sujin',
  age: false, // 오류 
  email: 'inpa@naver.com' // 오류
};

하지만 이게 타입인지 객체인지 뭔지 가독성이 좋지 못하다보니.. 이를 극복하기 위해 타입스크립트는 type 리터럴이라고 불리우는 alias 기능과 interface 라는 문법을 추가했다. 

// type alias
type comUser = {
    name: string,
    age: number
}
 
let user1: comUser = {
    name: 'happy',
    age: 21
};
 
let user2: comUser = {
    name: 'sujin',
    age: false, // 오류
    email: 'zisuzin1978@gmail.com' // 오류
};

 

타입 - Any

기존 자바스크립트로 구현되어 있는 웹 서비스 코드에 타입스크립트를 점진적으로 적용할 때 활용하면 좋은 타입이다.

단어 의미 그대로 모든 타입에 대해서 허용한다는 의미를 갖는다.

let str: any = 'hello';
let num: any = 20;
let arr: any = ['apple', 5, false];

 

타입 - Unknown

말그대로 Unknown은 알 수 없는 타입을 의미하며, any와 같이 모든 데이터 타입을 받을 수 있다.

let a: any = 12;
let u: unknown = 12;

'any'와의 차이점이라면 둘의 차이 '엄격함'에 있다.

예를 들어 any타입 같은 경우 아래와 같이 number 타입의 데이터를 넣고 string 타입의 메소드 length를 사용했을때 어떠한 에러를 발생시키지 않고 그냥 undefined를 반환한다.

let val : any = 20;
console.log(val.length); // undefined

하지만 unknown 타입은 any 타입과 동일하게 모든 값을 허용하지만, 할당된 값이 어떤 타입인지 모르기 때문에 함부로 연산을 할 수 없다는 특징을 가지고 있다.

그래서 다음과 같이 미리 에디터 자체에서 에러를 띄워준다.

let valNum: unknown = 20;
let valStr: unknown = '몰라!';

console.log(valNum.length); // 에러 : "개체가 알 수 없는 형식입니다." 
console.log(valStr.length); // 에러 : "개체가 알 수 없는 형식입니다."

이런 경우 자바스크립트에서 자주 쓰이는 typeof 연산자를 통해 타입을 검사해서 해결할수 있다.

let valNum: unknown = 20;

if (typeof valNum === "number") {
  console.log(valNum.length);
}

이처럼 any 대신 unknown 타입을 사용하면 체크를 해야 되는 코드는 많아졌지만, 사전에 문제가 되는 부분을 방지할 수 있으므로 any 타입에 비해 안정적인 애플리케이션을 개발할 수 있게 된다.

 

타입 - Null / Undefined

자바스크립트에서도 undefined가 하나의 자료형이자 값이었던 것처럼, 타입스크립트에서도 null과 undefined 타입이 있다.

let nullval: null = null;
let undefinedval: undefined = undefined;

기본적으로 null  undefined는 다른 모든 타입의 하위 타입으로 치부된다. 이말은 즉슨, null과 undefined를 여러 타입에 할당할 수 있음을 의미한다.

 

타입 - Never

never 타입은 number나 string 처럼 어떠한 자료형 값을 담기 위한 타입이 아니다.

never 타입은 타입스크립트에서 잘못된 것을 알려주기 위한 키워드로써, 단어 그대로 절대 발생할 수 없는 타입을 나타낸다고 보면 된다.

함수의 끝에 절대 도달하지 않는다는 의미를 지닌 타입이다.

// 이 함수는 절대 함수의 끝까지 실행되지 않는다는 의미
function neverEnd(): never {
  while (true) {

  }
}

// 절대 할당될 수 없음을 의미
const never: [] = [];
never.push(2);

 

타입 - Void

반환 값이 없는 함수의 반환 타입이다. 아래와 같이 return이 없거나 return이 있더라도 반환하는 값이 없으면 함수의 반환 타입을 void로 지정한다.

function printStr(): void {
  console.log('test');
}

function returnNothing(): void {
  return;
}

 

타입 - Literal 

문자열과 숫자에 한해서 직접 값 자체를 타입으로 선언이 가능하다.

① 숫자 리터럴 타입 (Numeric Literal Types)

아래 코드에서 허용한 숫자 외에 다른 숫자를 사용하게 되면 에러가 발생한다.

type user = 1 | 2 | 3;

const userKim: user = 1;
const userPack: user = 5;

 

② 문자 리터럴 타입 (String Literal Types)

문자열 리터럴 타입은 문자열에 값을 정확 지정할때 사용된다.

아래 코드에서 fruit에서 허용한 3개의 문자열 외에 다른 문자열을 사용하게 되면 에러가 발생한다.

type fruit = "apple" | "banana" | "pine";

const myfruit1: fruit = "apple"; // (O)
const myfruit2: fruit = "cukkie";  // (X): Type 'aaa' is not assignable to type 'fruit'.

 

타입 - Union

2개 이상의 타입을 허용하는 경우, 이를 유니언(Union)이라고 한다. (OR 의 의미로도 쓰인다.)

| (파이프)를 통해 타입을 구분하며, 괄호는 단일 타입일 때는 안써도 되지만 배열일 경우 씌워야 한다.

let union: string | number;
union = 'Hello World!';
union = 1234;
union = false; // 오류 : Type 'false' is not assignable to type 'string | number'.
let array: (string | number)[] = ['food', 1, 2, 'rice', 'bread', 3];
// Or
let array: Array<string | number> = ['food', 1, 2, 'rice', 'bread', 3];
function testFn(pm: string, pm2: boolean | number) {
  // ...
}

testFn("hihi", true);

 

타입 - Generic

제네릭은 타입을 변수화 하였다고 생각하면 된다.

우리가 데이터를 직접 다루지않고, 변수라는 상자에 담아 사용하는 이유는 재사용성을 높이기 위해서다.

이처럼 타입을 마치 함수 파라미터 처럼 나중에 대입하도록 하여 재사용성을 높이기 위해 탄생한 타입이 제네릭 타입이라고 이해하면 된다.

 

제네릭의 선언 문법을 <T> 꺾쇠 괄호 기호를 이용한다. 안의 T 는 변수명으로서 아무 문자로 명명해줘도 상관없다.

type arrs<T> = T[];

const numArr: arrs<number> = [1, 2, 3, 4, 5];
const strArr: arrs<string> = ['a', 'b', 'c', 'd', 'e'];
const mixArr: arrs<string | number> = ['a', 20, 'd', 34, 'e'];
function getTxt<T>(pm: T): T {
   return pm;
}

getTxt<string>('hello'); // 'hello'
getTxt<number>(20); // 20
getTxt<boolean>(true); // true

 

타입간 대입 가능한 표

초록색 체크는 strict 모드가 false일때만 허용되는 것이므로 사실상 X 라고 봐도 무방하다.

표를 읽는 법은 다음과 같다. "데이터( any → ) 가 들어갈수 있는 타입은 자기자신과 unknown ~ null 타입에 대입될수 있으며, never 타입에는 대입될 수 없다" 라고 해석하면 된다.

LIST
profile

dev_genie

@dev_genie

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!