TypeScript

[TypeScript] 타입

wwxs 2024. 8. 19. 15:18

타입(Type)

  • 타입 명시(작성)가 필수 사항 X → 프로그램의 안정성과 가독성을 높이는 역할

 

타입 명시 방법

  • 타입 어노테이션 (type annotation - 타입 주석)
  • 변수명 뒤에 콜론을 사용하여 JS 코드에 타입을 정의

 

타입스크립트 타입의 종류

 

1. 기본 타입(원시 타입 - string, number, boolean 등)

  • 변수명 뒤에 콜론 사용
  • typeof 연산자 사용 시 나타내는 변환값과 동일한 이름으로 명시 (소문자)
더보기
더보기
let name: string = '홍동현';
// 권장) 변수명: 타입명 = 값;
let age: number = 50;
let isStudent:boolean = false;

2. 배열(list, array) 타입

  • 순서가 있는 요소의 모을을 나타내는 자료 구조
  • 변수명 뒤에 콜론 사용 → 기본타입명 뒤에 배열을 나타내는 [ ]를 첨부
  • 제네릭 타입 → Array<기본타입>
더보기
더보기
// 변수명 뒤에 콜론 사용
let list1: string[] = ['1', '2', '3'];

// - 제네릭 타입
let list2: Array<number> = [4, 5, 6]

3. void 타입

  • void : 아무런 값이 없다 → 주로 함수에서 반환값이 없거나 return 키워드가 있더라도 반환하는 값이 없을 때 사용되는 타입
더보기
더보기
function voidType(parameter: number): void {
  // 함수의 타입 정의
  // >> 파라미터(매개변수)와 반환값(return값) 정의 가능
  // >> TS에서 "파라미터"에 타입을 명시하지 않으면 오류 발생
  //    : 함수 내에서 사용할 변수에 대한 안정성을 요구
  //    : 변수의 타입 명시와 동일

  // >> 반환값의 타입 명시는 파라미터를 정의하는 ()소괄호 뒤에
  //    콜론을 붙여 정의
  console.log(parameter);
  return;
}

voidType(10);	// 10

4. null & undefined 타입

  • null 타입 : 아무것도 없음, 데이터가 잘못된 경우
  • undefined 타입 : 변수 생성은 했지만 안에 값이 없을 경우

5. any 타입 (모든)

  • 모든 타입에 대해 허용하는 타입
  • 타입 검사 오류가 발생하는 것을 방지 (모든 타입과 호환 가능)
  • TS를 JS처럼 사용

6. never 타입

  • 절대 발생하지 않는 값의 타입
  • 함수가 예외를 발생시키거나 끝나지 않을 때 사용
더보기
더보기
function error(message: string): never{
  throw new Error(message);
}

// error('에러 발생!');  - Error

타입스크립트의 객체 타입

객체 타입 지정(명시)

  • { } 중괄호를 사용하여 표현
  • 각 데이터별 타입 명시의 구분은 세미콜론(;) 사용을 권장
더보기
더보기
const user: {
  // 각 타입 구분 시 콤마와 세미콜론 모두 사용 가능
  // >> 세미콜론 사용을 권장
  name: string;
  height: number;
  favorite: any[];
  // 타입에서 명시한 속성은 반드시 객체 내부에 존재
} = {
  // 객체 내부에서 각 속성의 구분은 콤마(,)로 표시
  name: '홍동현',
  height: 169,
  // hobby: 'exercise' - Error
  // >> 객체는 타입 명시를 하지 않은 속성은 정의할 수 X
  favorite: [1, '운동', false, null, undefined, ['안녕', 1]]
}

 

객체의 선택 속성

  • 선택적 프로퍼티
  • 속성명 "뒤"에 물음표(?)를 붙여 해당 속성이 존재하지 않을 수도 있음을 표현
더보기
더보기
const ldk: {
  name: string;
  height?: number;  // 타입 명시 속성 뒤에 물을표를 작성 (선택적 프로퍼티)
} = {
  name: '이도경',
  // height: 157 - 생략해도 오류X
}

 

읽기 전용 속성

  • 속성명 "앞"에 readonly 키워드를 사용하여 해당 속성의 재할당을 금지
  • 해당 키워드가 붙은 속성은 const 키워드를 사용하여 정의한 변수와 유사
더보기
더보기
const readonlyName: {
  readonly name: string;
  readonly age?: number;
  address?: string;
} = {
  name: '홍동현',
  age: 50,
}

// readonlyName.age = 30; - Error

타입 별칭

  • 새로운 타입 이름을 생성해서 기존의 타입을 참조할 수 있게 하는 기능
  • 코드의 재사용성과 가독성 향상
  • type 타입별칭 = 타입;

1. 변수 타입 별칭

더보기
더보기
type TextType = string;
// >> 타입 별칭은 다른 코드와의 식별을 위해 대문자로 시작

let textMsg: TextType = '텍스트 문자열입니다.'

type NumberType = number;
let num: NumberType = 1923;

2. 객체 타입 별칭

  • 타입 별칭 내에서도 선택적 프로퍼티 & 읽기 전용 속성 사용 가능
더보기
더보기
type UserType = {
  name?: string;
  readonly height: number;
};

const user1: UserType = {
  name: "홍동현",
  height: 169,
};

// user1.height = 170; // Error

const user2: UserType = {
  // name: '이도경',
  height: 157,
};

3. 함수 타입 별칭

  • User 타입인 매개변수를 받아 boolean 타입의 반환값을 생성하는 함수
더보기
더보기
type User = {
  id: string;
  password: string;
};

type ValidUser = (user: User) => boolean;

const isValidUser: ValidUser = (user) => user.id !== "";

let userA: User = {
  id: "qwerty",
  password: "qwe123",
};

let userB: User = {
  id: "",
  password: "qweqwe123123",
};

console.log(isValidUser(userA)); // true
console.log(isValidUser(userB)); // false

Union(유니언) 타입

  • 여러 타입 중 하나가 될 수 있는 값을 나타내는 방법
  • 값에 허용된 타입을 두 개 이상으로 지정
  • OR 연산자 (| ; vertical bar) 기호를 사용하여 표현

유니언 타입의 사용

  • 변수, 함수의 매개변수, 반환값 등에서 모두 사용 가능
  • 타입의 유연성을 제공
  • 무분별한 any 사용을 방지
  • type UnionType = Type1 | Type2 | ...;
더보기
더보기
type VariableType = string | number | boolean | string[];

let value: VariableType = '문자';
value = 123;
value = true;
value = ['안녕', '반가워'];

 

타입 별칭에서 union 타입 사용시

  • 정확한 타입 지정을 위해 타입 가드를 사용
  • 타입 가드 : 조건문을 통해 타입을 좁혀나가는 방식
더보기
더보기
type Union = number | string;

function getAge(age: Union){  
	if(typeof age === 'number'){
    	age = age.toFixed();
   		return age;
  	} else{
    	age = age.toUpperCase();
    	return age;
  	}
}

console.log(getAge(12.345));  // 12
console.log(getAge('12 years old'));  // 12 YEARS OLD

Intersection(인터섹션) 타입

  • 여러 타입을 하나로 결합하여 모든 타입의 기능을 갖춘 단일 타입을 생성
  • 여러 타입을 모두 만족하는 하나의 타입
  • And 연산자 (&) 를 사용하여 구현
  • type 타입별칭 = Type1 & Type2 & ...;
더보기
더보기
type Admin = {
  isAdmin: boolean;
}

type User =  {
  id: string;
  password: string;
}

// 관리 사용자
type AdminUser = Admin & User;

function createAdminUser(user: User): AdminUser {
  // 스프레드 연산자를 사용하는 새로운 객체 생성
  return { ...user, isAdmin: true };
}

let newAdminUser: User = {
  id: 'qwe123',
  password: 'qweqwe123123'
}

let adminUser1 = createAdminUser(newAdminUser);
console.log(adminUser1); 
// { id: 'qwe123', password: 'qweqwe123123', isAdmin: true }

리터럴 타입(Literal, 문자 그대로의)

  • 특정 '값' 만을 가질 수 있는 타입을 정의할 때 사용

리터럴 타입의 종류

1) const 키워드를 사용하여 직접 리터럴 값을 할당(초기화)

더보기
더보기
let str1 = '안녕하세요'; // string 타입
str1 = 'hello';
str1 = '곤니치와';

const str2 = '반갑습니다.'; // "반갑습니다." 타입
// str2 = 'hi';		- Error
// str2 = '니하오';	- Error

2) 변수에 타입 명시를 리터럴 값으로 명시

더보기
더보기
let num1: 123 = 123; // 123 타입
// num1 = 234;		- Error
// num1 = 345;		- Error

let boo1: true = true; // true 타입
// bool1 = false;	- Error

 

리터럴 타입의 활용

  • 주로 type 키워드(타입 별칭)와 함께 사용
  • 유니언 타입과 함께 사용하여 다양한 값을 표현함과 동시에 제한 가능
  • 변수 혹은 매개변수가 특정 값들 중 하나만을 가질 수 있도록 제한
더보기
더보기
//? 리터럴 타입 예시
// 1) Directions(방향) 타입을 정의
type Directions = 'up' | 'down' | 'left' | 'right';

let moveUp: Directions;
moveUp = 'up';
// moveUp = '위';

// 2) 함수의 인자로 리터럴 타입을 지정하여 특정 값으로 제한
function setAlignment(align: 'left' | 'center' | 'right') {
  // 함수 내용
  // let container = document.querySelector('#container');
  // container.style.textAlign = align;
}

setAlignment('center');
// setAlignment('중앙'); - Error

// 3) IoT 국비반 학생 관리 시스템

type Students = '이승아' | '이도경' | '정재원' | '최준혁' | '최소윤';
let students: Students;

// students = '김준일';

// +) 리터럴 타입의 경우 여러 타입의 혼합이 가능
type mixedType = 'yes' | 'no' | 1 | 2 | 3;

let gameState: mixedType;
gameState = 'yes';
gameState = 3;
gameState = 1;
// gameState = 123;
// gameState = '노우';
gameState = 'no';

 

객체 리터럴 타입

  • 실제 객체 데이터 정의
더보기
더보기
type UserType = {
  name: '홍동현';
  height: 169;
}

let user: UserType = {
  name: '홍동현',
  // height: 170 // '170' 형식은 '169' 형식에 할당할 수 없습니다.
  height: 169
};

객체의 구조적 타이핑(덕 타이핑)

  • 객체의 타입을 실제 값보다는 그 구조나 멤버에 의해 결정하는 방식
  • 객체의 형태가 같다면, 같은 타입으로 간주
더보기
더보기
type Person = {
  name: string;
  age: number;
}

function greet(person: Person) {
  console.log(`Name: ${person.name}, age: ${person.age}`);
}

// Person 타입이 명시적으로 구현되지 않은 객체 생성
const p1 = {
  name: '홍동현',
  age: 50
}

const p2 = {
  name: '이도경',
  age: 60,
  hobby: '배구보기'
}

const p3 = {
  name: '정수은'
}

greet(p1); // Person과 구조가 일치하기 때문에 Person 취급
greet(p2); // 구조적 타이핑에 의해 Person 취급 (hobby속성을 무시)
// greet(p3); // >> Person 타입 속성 구조와 일치하지 않음

 

중첩된 객체 타입 정의

더보기
더보기
type Address = {
  street: string;
  readonly city: string;
  zipCode?: string; // 선택적 프로퍼티 (옵셔널)
}

type UserProfile = {
  username: string;
  email: string;
  address: Address;
}

let userA: UserProfile = {
  username: '장지민',
  email: 'qwe123',
  address: {
    street: '123 St',
    city: 'Busan'
  }
}
// userA.address.city = '대전';
userA.address.street = '중앙대로';

 

객체의 인덱스 서명

  • 객체의 모든 속성에 대해 타입을 정의하지 않고 키와 값의 타입만 정의하여 구조를 유연하게 적용하는 방법
더보기
더보기
type UserDataType = {
  name: string; // - 일반적인 객체 속성 타입 명시
  
  //? 인덱스 서명 사용 방법
  // [propertyName: indexType]: valueType;
  // 키의 타입과 값의 타입을 미리 명시
  [key: string]: string | number | boolean; // 키는 string 사용을 권장
  // >> valueType에는 어떤 타입이든 가능
}

let user1: UserDataType = {
  name: '이승아',
  height: '123',
  age: 50,
  isTeacher: true
}

// user1.email = [123, 234];
user1.email = 'qwe123';

타입스크립트의 함수

더보기
더보기
function greet(name: string): string {
  return `Hello ${name}`;
}

//? 함수에 타입 별칭을 사용하는 경우
// >> 화살표 함수의 체계를 사용

type ArrowFuncType = (name: string) => string; 

const arrowFunc: ArrowFuncType = (name) => {
  return `Hi ${name}`
}

console.log(arrowFunc('선하영'));
console.log(arrowFunc('지수민'));

 

선택적 매개변수와 기본 매개변수

1) 선택적 매개변수

  • 함수 호출시 생략 가능
  • 변수명 뒤에 ? 작성

2) 기본 매개변수

  • 기본값을 할당
  • 함수 호출 시 생략하는 경우에 기본값을 자동 할당
  • 매개변수명 = '기본값'
더보기
더보기
function select(name?: string, greeting: string = '안녕') {
  if (name) {
    console.log(`${greeting}, ${name}`);
  } else {
    console.log(`${greeting}, guest`);
  }
}

select(); // 안녕, guest
select('이승아'); // 안녕, 이승아
select('반가워'); // 안녕, 반가워

select(undefined, '반가워') // 반가워, guest

select('이도경', '반가워'); // 반가워, 이도경

선택적 매개변수와 기본 매개변수 사용 시

  • 선택적 매개변수는 반드시 필수 매개변수(인자로 전달) 뒤에 작성
  • 기본 매개변수는 필수와 선택적 매개변수 양쪽에 작성 가능 (어디든)
  • 기본 매개변수가 앞서는 경우 생략하려면 반드시 undefined를 전달

Rest(나머지) 매개변수

  • 함수에 전달하는 여러 개의 매개변수를 그룹화하여 배열로 전달하는 기능
  • ...연산자(spread 연산자)를 사용하여 매개변수명 앞에 사용
더보기
더보기
function sum(a: number, b: number, ...c: number[]) {
  return c.reduce((c1, c2) => c1 + c2, 0); // c1 += c2
}

console.log(sum(1, 2, 3, 4, 5)); // 12
console.log(sum(1, 2)); // 0
console.log(sum(1, 2, 10, 20, 30)); // 60

Rest 매개변수의 주의점

  • 항상 매개변수 리스트의 마지막에 위치
  • 타입 명시를 배열로 작성

'TypeScript' 카테고리의 다른 글

[TypeScript] generic(제네릭)  (0) 2024.08.23
[TypeScript] 인터페이스  (0) 2024.08.20
[TypeScript] 기본 문법  (0) 2024.08.19
[TypeScript] 환경설정  (0) 2024.08.19
[TypeScript] 타입스크립트  (0) 2024.08.19