본문 바로가기
개발공부

#2. 타입스크립트 기본

by 반류연 2025. 2. 18.

*이 게시물은 이정환 강사님의 '한 입 크기로 잘라먹는 타입스크립트' 강의를 수강한 뒤 정리한 글입니다.

 

 

 

원시타입(Primitive Type)

  • 동시에 한개의 값만 저장할 수 있는 타입.
  • number, string, boolen, null, undefined, 리터럴 타입

※ 만약 null을 임시값으로 설정하고 싶다면? : strictNullChecks 옵션을 false로 설정(tsconfig.json)

let numA : null // js에선 가능
let numA: number = null; // ts 에러

 

※ 리터럴 타입 : 딱 하나의 값만 포함하는 타입.

let numA: 10 = 10; // 10외의 값 저장 x
let strA: "hello" = "hello"
let boolA: true = true;
let boolB: false = false;

 

 

배열

// 일반 배열정의
let numberArr: number[] = [1,2,3]
let strArr : string[] = ['hello','im','van']

// 제네릭 방식: 제네릭은 차후 정리
let boolArr : Array<boolean> = [true, false, true]

 

※ 다양한 타입의 배열요소를 가질 땐 어떻게 정의할까? : 유니온(Union) 타입 사용

let multiArr : (number | string)[] = [1, 'hello']

 

※ 다차원 배열 타입 정의

let doubleArr : number[][] = [
	[1,2,3],
    [4,5]
]

 

 

튜플

  • 길이와 타입이 고정된 배열
  • JS는 없고 TS에만 있는 특수한 타입
  • 본질은 배열이기 때문에 배열의 메소드 역시 사용 가능(ex: push, pop)
let tup1 : [number, number] = [1,2]
let tup2 : [number, string, boolen] = [1, 'hi', true]

 

※ 튜플을 왜 사용하는 걸까?

길이와 값을 고정해놓으면 값이 잘못 들어갔을때 바로 오류를 찾을 수 있음

// 유저 정보 저장하는 튜플
// 0번 인덱스에는 회원의 이름, 1번 인덱스에는 아이디 순번 저장

const users : [string, number][] = [
	["이정환", 1],
    ["김철수", 2],
    ["최하니", 3],
    [4, "조땡땡"] // 오류발생
]

 

 

객체

  • 객체의 타입은 'object' 가 아닌 '객체 리터럴 타입'을 사용해야 한다!
    • 이유: object 타입은 단순히 값이 객체라는 것을 표현할 뿐, 해당 객체가 가지고 있는 프로퍼티 정보를 전혀 가지고 있지 않음. 따라서 객체.key 형태로 값에 접근하면 오류가 발생함.
    • 따라서 객체의 프로퍼티를 직접 나열하는 객체 리터럴 방식을 사용.
// 객체 리터럴 타입
let user : {
	id: number,
    name : string
} = {
	id: 1,
    name: "이정환"
};

user.id // 1 출력

 

 

타입스크립트는 객체의 타입을 정의할 때 프로퍼티를 기준으로 객체의 구조를 정의하듯이 타입을 정의한다!
-> 구조적 타입 시스템

 

※ 특수한 프로퍼티 정의하기

1. 선택적 프로퍼티(Optional Property)

  • 있어도 되고 없어도 되는 프로퍼티를 정의
  • 프로퍼티 이름 뒤에 '?' 를 붙임
let user : {
	id ?: number,
    name: string
} = {
	id: 1,
    name: "이정환"
}

user = {
	name: "홍길동" // 정상
}

 

2. 읽기 전용 프로퍼티(Readonly Property)

  • 수정x, 읽기만 할 수 있는 프로퍼티 정의
let user : {
	id: number,
    readonly name : string
} = {
	id : 1,
    name: "이정환"
}

user.name = "최정환" // 오류! 수정 불가능

 

 

타입 별칭

  • 변수를 선언하듯 타입을 별도로 정의할 수 있는 기능 
  • 'type 타입이름 = 타입' 형태 
  • 변수 선언 시 타입 주석과 함께 사용할 수 있음
  • 동일 스코프에선 중복된 이름으로 여러개의 별칭을 선언할 수 없음(변수와 동일)
// 타입별칭 선언
type User = {
	id: number,
    name: string,
    nickname: string,
    birth: string
}


// 타입별칭 사용
let user1 : User = {
	id: 1,
    name: "이정환",
    nickname: "winterlood",
    birth: "1997.01.07"
}

let user2 : User = {
	id: 2,
    name: "홍길동",
    nickname: "houhou"
    birth: "2001.12.17"
}

 

 

인덱스 시그니처

  • 객체 타입을 유연하게 정의할 수 있도록 돕는 특수문법
  • 정의해야 할 타입이 많을 때 사용하면 유용
// ex:  국가 언어코드 저장하는 객체 정의

type ContryCodes = {
	Korea: string,
    UnitedState: string,
    UnitedKingdom: string, 
    
    // ... 이렇게 100개씩 지정하려면 너무 오래걸리고 유지보수도 힘듦.
}


// 인덱스 시그니처 사용
type ContryCodes = {
	[key: string] : string;
}

let contryCodes : CountryCodes = {
	Korea: "ko",
    UnitedState: "us",
    UnitedKingdom: "uk"
    
    // ... 등등 100개 국가 정의
}

 

  • 만약 반드시 정의해야 하는 프로퍼티가 있다면? : 직접 명시하면 됨
  • 이 때, 새로 추가한 프로퍼티의 value 값은 기존 인덱스 시그니처의  value 값과 타입이 호환/일치해야 함
type CountryCodes = {
	[key: string] : string,
    Korea: string
    USA: number // 오류
}

 

  • 다양한 타입의 값으로 인덱스 시그니처를 사용하고 싶다면?  : 유니온(Union) 타입 사용
type countryCodes {
  [key: string]: string | number;  // 값이 'string' 또는 'number' 타입일 수 있음
}

let countryCodes : countryCodes = {
	korea : "ko",
    usa : 123
}

 

열거형 타입(Enum)

  • JS는 없고 TS에만 존재하는 타입
  • 여러개의 값을 나열하는 용도로 사용
  • 숫자형 enum과 문자형 enum이 있음
  • TS에만 존재하나, 컴파일 후 다른 TS 타입들처럼 사라지지 않고 JS 객체로 변환됨
enum Role {   // 괄호 바로 쓰는 것 주의!
	ADMIN,
    USER,
    GUEST
}

 

  • enum에는 각 멤버에 숫자를 할당할 수 있고, 멤버들을 값으로 활용할 수도 있음
  • 따로 숫자를 할당하지 않으면 자동으로 0부터 할당됨.
enum Role {
	ADMIN = 0,
    USER = 1,
    GUEST = 2
}

const user1 = {
	name: "이정환",
    role : Role.ADMIN
}

const user2 = {
	name: "홍길동",
    role : Role.USER
}

const user3 = {
	name: "이정환",
    role : Role.GUEST
}

 

enum Role {
  ADMIN = 10, // 10 할당 
  USER,       // 11 할당(자동)
  GUEST,      // 12 할당(자동)
}

const user1 = {
  name: "이정환",
  role: Role.ADMIN, // 10
};

const user2 = {
  name: "홍길동",
  role: Role.USER, // 11
};

const user3 = {
  name: "아무개",
  role: Role.GUEST, // 12
};

 

  • 문자형 enum: 모든 멤버의 값이 문자열 값인 열거형
  • 문자형 enum은 객체 선언시 대소문자나 철자 실수로 인한 오류를 방지하는데 유용함
enum Language {
	korean = "ko",
    english = "en"
}

enum Role {
  ADMIN,
  USER,
  GUEST,
}


// 숫자형, 문자형 enum 을 섞어 쓸 수 있음
const user1 = {
	name: "이정환",
    role: Role.ADMIN,
    lang : Language.korean
}

 

 

any 타입

  • TS에서만 존재. 타입 검사를 받지 않는 일종의 치트키 타입.
  • 범용적으로 사용하기 좋으나, 타입검사를 받지 않아 오류 발생 위험이 높은 만큼 되도록 사용하지 않는 것이 좋음.

 

Unknown 타입

  • any와 비슷하지만 좀 더 안전한 타입
  • 어떤 타입의 값이든 할당받을 수 있지만, 반대로 다른 변수에 할당하는 것은 안 됨. => 값의 "저장" 만 가능!
  • 사칙연산, 메서드 사용 X
let unknownVar = unknown;

unknownVar = "" // 정상
unknownVar = 1 // 정상
unknownVar = () => {} // 정상

let num: number = 10;
num = unknownVar; // 오류
unknownVar * 2 // 오류
  • 만약 unknown 타입의 값을 받았는데 연산하고 싶다면? 
    -> 조건문으로 타입을 좁혀야 한다!
if(typeof unknownVar === "number"){
	unknownVar * 2
}

 

 

void 타입

  • 아무 값도 없음을 의미.
  • 보통 return 값이 없는 함수의 반환값 타입을 정의할 때 사용
  • 변수의 타입으로 활용할 경우, 오직 undefined 값만 담을 수 있음
    • tsconfig.json에서 'strictNullCheck 옵션'을 false 처리한다면 void에 null도 담을 수 있게 됨!
// 반환값 없는 함수의 타입을 지정할 떄
function fun2(): void {
	console.log('hello')
}

// 변수를 void 타입으로 선언할 때
let a: void;
a = undefined

 

 

never 타입

  • 불가능을 의미하는 타입.
  • 보통 무한루프처럼 함수가 어떤 값도 반환할 수 없는 상태에서 사용.
  • 의도적인 오류를 발생시킬 경우에도 반환값을 never 타입으로 정의.
  • any를 포함한 어떤 값도 해당 타입 변수에 값을 담을 수 없음.
// 무한루프
function func3(): never {
	while(true) {}
}

// 의도적으로 오류를 발생시킬 때
function func4():never {
	throw new Error()
}

'개발공부' 카테고리의 다른 글

#6. 클래스  (0) 2025.02.27
#5. 인터페이스  (0) 2025.02.26
#4. 함수와 타입  (0) 2025.02.25
#3. 타입스크립트 이해하기  (0) 2025.02.20
#1. 타입스크립트 개론  (0) 2025.02.17