TIL

TypeScript 강의 (4) ( 타입 )

황민도 2024. 7. 19. 02:21

내일배움캠프 스파르타 코딩클럽

[ 타입 ]

 

타입에 대한 제대로 된 이해가 중요한 이유!

타입을 제대로 이해하면 오류들을 미리 방지할 수 있다.

 

< 1. 기본 타입 훑어보기 >

 

1. boolean

 - boolean 타입은 참(true) 또는 거짓(false) 값을 나타낸다.

 - 이외의 값은 표현을 할 수 없다.

 - 조건문, 비교 연산 등에서 주로 사용된다.

 - 예시 :

function isValidPassword( password: string ): boolean {
	return password.length >= 8;
}

const password = "q1w2e3r4!";
const valid = isValidPassword(password);

if (valid) {
	console.log("유효한 패스워드입니다!");
} else {
	console.log("유효하지 않은 패스워드입니다.!");
}

중요한건

2가지의 상태(켜짐/꺼짐, 유효함/유효하지 않음)를 표현하고 싶은경우 => boolean을 사용해야 하고,

3가지 이상의 상태를 표현하고 싶은 경우 => enum 이나, srting 을 사용해야 한다.

 

2. number

 - number 타입은 TypeScript 에서 사용하는 모든 숫자를 나타낸다.

 - 보통 일반적인 프로그래밍 언어(정적 타입 언어)에서는 각 숫자의 유형마다 타입이 다르게 있다.

   (

     1. 정수는 short, int, long 을 사용하고

     2. 실수는 float, double 을 사용한다.

   )

 - 하지만, TypeScript 에서는 number 타입이 정수, 실수 뿐 아니라 2, 8, 16진수까지 표현할 수 있다.

 - 모든 수치 연산에 사용되는 값은 number 타입으로 명시를 해줘야 한다.

 - 예시 : 

function calculateArea( radius: number ): number {
	return Math.PI * radius * radius;
}

const radius = 5;
const area = calculateArea(radius);
console.log(`반지름이 ${radius}인 원의 넓이: ${area}`);

Math.PI (3.141592) * radius * radius 와 같이 무리수(유리수가 아닌 실수. 즉, 분수형태로 정확하게 표현할 수 없는 수)와

정수를 곱한 값도 number 로 취급을 할 수 있기 때문에 calculateArea 함수의 리턴 타입도 number 이다.

 

3. string

 - string 타입은 텍스트 데이터를 나타낸다.

 - 작은 따옴표('), 큰 따옴표("), 백쿼트(`) (백틱이라고 도 함) 를 사용하여 문자열을 표현할 수 있다.

   ( ES6 부터 생긴 템플릿 리터럴을 사용할 때 백쿼트를 써서 사용한다. ) 

 - string 타입은 텍스트를 조작하거나 출력할 때 사용할 수 있다.

   (

    1. 텍스트와 텍스트가 합쳐져야 되는 경우

    2. 텍스트에서 특정 문자열을 찾아야 하는 경우

    3. 기타 등등 텍스트에서 필요한 연산은 string 타입에서 전부 할 수 있다.

   )

 - 예시 :

function great( name: string ): string {
	return `안녕, ${name}!`;
}

const name = "Spartan";
const greeting = greet(name);
console.log(greeting);

1. return `안녕, ${name}!`; 이 코드가 템플릿 리터럴 이다.

2. 템플릿 리터럴을 보면 백쿼트로 감싸진 구역에 문자열과 표현식이 같이 사용된다.

 - 안녕, => 문자열

 - ${name} => 표현식

 - ! => 문자열

3. 기존에는 문자열과 표현식을 사용하기 위해서는 + 연산자로 계속 덕지덕지 이어 붙여야 되는 번거로움이 있었는데

    템플릿 리터럴이 등장한 이후에는 + 연산자를 사용하지 않아도 된다.

 

4. 배열

 - 배열은 기본타입에 [] 가 붙은 형태의 타입을 뜻한다.

 - 예시 : 

function calculateSum( numbers: number[]): number {
	let sum: number = 0;
	for (let i = 0; i < numbers.length; i++) {
		sum += numbers[i];
	}
	return sum;
}

const testScores: number[] = [90, 85, 78, 92, 88];
const sumScore = calculateSum(testScores);
console.log(`점수의 총합: ${sumScore}`);

 

5. 튜플(tuple)

 - 튜플은 서로 다른 타입의 원소를 순서에 맞게 가질 수 있는 특수한 형태의 배열이다.

 - 배열은 number[], string[] 처럼 같은 타입의 원소만 가질 수 있었다.

const testScores: number[] = [90, 85, 78, 92, "88"];

위의 코드처럼 마지막 원소를 string 타입으로 넣으면 에러가 발생한다.

숫자만 넣어줘야 한다. 즉, 같은 타입의 원소만 취급 한다.

 

 - 하지만, 튜플은 어떤 타입의 원소를 허용할 것인지 정의만 해주면 된다.

   ( 얼마든지 허용된 타입의 데이터들을 저장할 수 있다. )

 - 예시 :

const person: [string, number, boolean] = ['Spartan', 25, false]; // Tuple 타입 배열
const person2: [string, number, boolean] = [25, 'Spartan', false]; // 오류

const testScores: any[] = [90, 85, 78, 92, "88"]; // Any 타입 배열
const testScores2: (number | string)[] = [90, 85, 78, 92, "88"]; // Union 타입 배열

1. person 이라는 튜플에 데이터를 더 저장하고 싶은데 그래도 상관없는가?

 - 원칙적으로는 데이터를 더 저장하는 것은 타입 안정성에 위배가 되는 행위이다.

 - 튜플에서도 배열의 메소드인  push를 사용하여 정의된 데이터 타입의 개수보다 더 저장할 순 있다.

   ( 하지만, 이렇게 억지로 데이터를 넣으면 튜플 구조가 내부적으로 변경이 되니 좋은 선택은 아니다. )

2. 그럼 맨처음같은 const testScores = [90, 85, 78, 92, "88"] 은 타입을 어떻게 해야하는가?

 - [ number, number, number, number, string ] 이 명확하고 구체적이긴 하지만 확장성 과 유연성이 안좋은 단점이 있다.

 - 그리하여 위와 같이 Any 타입 배열, Union 타입 배열 이 있지만

   Any 타입 배열은 타입 검사 장점을 무력화할 수 있으므로 가급적 사용을 피하는게 좋다.

   그래서 위와 같이 많은 수가 필요로 할때Union 타입 배열이 확장성과 유연성을 고려해 보았을 때 적합하다고 본다.

 

6. enum

 - enum 은 열거형 데이터 타입이라고도 한다.

 - 다양한 상수를 보다 더 이해하기 쉬운 문자열 이름으로 접근하고 사용할 수 있게 하는 타입이다.

 - enum 안에 있는 각 요소는 값이 설정되어 있지 않으면 기본적으로 숫자 0으로 시작한다.

 - enum 안에 있는 요소에는 number 혹은 string 타입의 값만 할당할 수 있다.

 - 예시 : 

enum UserRole {
	ADMIN = "ADMIN",
	EDITOR = "EDITOR",
	USER = "USER",
}

enum UserLevel {
	NOT_OPERATOR, // 0
	OPERATOR // 1
};

function checkPermission( userRole: UserRole, userLevel: UserLevel): void {
	if (userLevel === UserLevel.NOT_OPERATOR) {
		console.log('당신은 일반 사용자 레벨이에요');
	} else {
		console.log('당신은 운영자 레벨이군요');
	}

	if (userRole === UserRole.ADMIN) {
		console.log("당신은 어드민이군요");
	} else if (userRole === UserRole.EDITOR) {
		console.log("당신은 에디터에요");
	} else {
		console.log("당신은 사용자군요");
	}
}

const userRole: UserRole = UserRole.EDITOR;
const userLevel: UserLevel = UserLevel.NOT_OPERATOR;
checkPermission(userRole, userLevel);

 enum은 명확하게 관련된 상수 값들을 그룹화하고자 할 때 사용하는게 좋다.

그러나 값의 수가 많지 않고, 값들 사이의 관계가 뚜렷하지 않으면 사용을 지양하는게 좋다.

windo@DESKTOP-6SMB85M MINGW64 ~/first/src
$ npx ts-node test.ts
당신은 일반 사용자 레벨이에요
당신은 에디터에요

실행을 하면 위와같이 출력되는 것을 확인할 수 있다.