💡 배열
◎ 타입이 1개일 경우
// 배열 기본 표현
let numArr: number[] = [1, 2, 3];
let strArr: string[] = ["hello", "im", "shyunu"];
// 배열 표현(제네릭문법)
let boolArr: Array<boolean> = [true, false, true];
배열을 저장하는 변수 이름 뒤에 타입 주석의 시작을 의미하는 콜론(:)을 작성하고, 배열요소타입[ ] 형식으로 배열 타입을 정의합니다. 숫자를 담는 배열이면 number[ ], 문자열을 담는 배열이면 string[ ] 으로 작성하면 됩니다. 또한, Array<배열요소타입> 형태인 제네릭 타입으로 배열의 타입을 정의할 수 있습니다. 전자의 경우가 더 코드도 짧기 때문에 저는 전자의 표현을 더 많이 사용할 예정입니다.
◎ 타입이 2개 이상일 경우
let multiArr = [1, "hello"];
만약, 다음과 같이 숫자, 문자열 이라는 다양한 타입의 배열 요소를 갖는 배열의 타입을 정의해야하는 경우에는 어떻게 할까요?
// 배열에 들어가는 요소들의 타입이 다양할 경우
let multiArr: (number | string)[] = [1, "hello"];
이와 같이 소괄호와 바( | )를 이용하여 타입을 정의할 수 있습니다. 소괄호 내부의 number | string은 배열 요소의 타입이 둘 중 하나라는 것을 의미합니다. 이렇게 바( | )를 사용하여 정의하는 문법을 유니온(Union) 타입이라고 부릅니다.
◎ 다차원 배열일 경우
// 다차원 배열의 타입을 정의하는 방법
let doubleArr: number[][] = [
[1, 2, 3],
[4, 5],
];
다차원 배열은 배열의 요소가 또 다른 배열인 구조를 가진 배열을 말합니다. 즉, 배열 안에 배열이 포함되어 있는 형태로, 데이터를 행렬이나 테이블처럼 계층적으로 표현할 수 있습니다. 다음과 같이 데이터타입 뒤에 [ ]를 연달아 작성하여 다차원 배열 타입도 정의할 수 있습니다.
💡 튜플
튜플이란, 자바스크립트에는 없는 타입스크립트의 특수한 타입으로 길이와 타입이 고정된 배열을 의미합니다. 지금까지 위에서는 배열의 타입을 고정하는 방법을 살펴보았지만, 아직까지는 배열의 길이까지 고정하는 방법을 모릅니다. 다음과 같은 방법을 통해서 고정된 길이를 갖는 배열 타입 또한 정의할 수 있습니다.
let tup1: [number, number] = [1, 2];
let tup2: [number, string, boolean] = [1, "2", true];
tup1은 길이가 2로 고정된 2개의 number 타입 요소를 갖는 튜플 타입이고, tup2처럼 다양한 타입을 갖는 튜플 타입도 정의할 수 있습니다.
// TypeScript
let tup1: [number, number] = [1, 2];
tup1.push(1);
tup1.push(1);
// JavaScript
let tup1 = [1, 2];
튜플도 결국 배열이기 때문에 tsc를 통해 튜플 타입이 정의된 타입스크립트 코드를 컴파일해보면 튜플은 결국 자바스크립트 배열로 변환되는 것을 확인할 수 있습니다. 그러므로 배열 메서드인 push나 pop을 이용하여 배열의 고정된 길이를 무시하고 요소를 추가하거나 삭제할 수 있습니다.
◎ 튜플을 사용하는 이유
const users = [
["김수현", 1],
["김하나", 2],
["김둘", 3],
["김셋", 4],
[5, "김다섯"] // 순서를 반대로 하여 추가된 배열
];
다음과 같이 회원 정보를 2차원 배열로 저장하는 상황이 있다고 해봅시다. 각 배열의 0번 인덱스에는 문자열 타입의 회원의 이름, 1번 인덱스에는 숫자 타입의 회원의 아이디를 저장하였습니다. 하지만 마지막줄처럼 순서를 잘못 배치하여 요소를 추가하는 경우에는 문제가 될 수 있습니다. 자바스크립트에서는 이러한 문제를 확인할 방법이 없기 떄문에 아래와 같이 타입스크립트에서는 튜플을 사용합니다.
const users: [string, number][] = [
["김수현", 1],
["김하나", 2],
["김둘", 3],
["김셋", 4],
// [5, "김다섯"] ❌
];
이와 같이 타입을 [문자열, 숫자]로 지정한 배열인 경우에는 타입이 반대로 입력된 배열이 적힌 코드에는 에러가 날 수 밖에 없습니다.
💡 객체
◎ 객체 타입 정의하기
⓵ object로 정의하기
let user: object = {
id: 1,
name: "shyunu",
};
user.id; //---❌
다음과 같이 user의 타입을 object(객체)로 정의하였고, user.id 처럼 점 표기법으로 객체의 특정 프로퍼티에 접근하고자 하였는데 오류가 발생하였습니다.
오류메세지를 확인해 보았는데 다음과 같이 object타입에는 id라는 프로퍼티가 존재하지 않는다고 나타납니다. 그런데 저는 분명 user 변수 안에 id와 name이라는 프로퍼티를 갖는 객체를 저장하였고 타입 또한 object로 잘 정의하였는데 왜 이러한 오류가 나타날까요?
그 이유는 타입스크립트의 object 타입은 값이 객체임을 표현하는 것 외에는 객체의 프로퍼티에 대한 정보를 전혀 가지고 있지 않기 때문입니다. 그래서 프로퍼티에 접근하려고 하면 오류가 발생하는 것입니다. 😢 이러한 경우에는 object가 아닌 객체 리터럴 타입을 사용해야합니다.
⓶ 객체 리터럴 타입으로 정의하기
let user: {
id: number;
name: string;
} = {
id: 1,
name: "shyunu",
};
user.id; // ⭕️
객체 리터럴 타입은 중괄호({ }) 안에 객체가 갖는 프로퍼티의 타입을 직접 나열하는 방식입니다. 변수 user의 타입을 number 타입의 id, string 타입의 name 프로퍼티를 갖는 객체 타입으로 정의하였습니다.
변수의 타입을 객체 리터럴 타입으로 정의하면 이제 타입 내에 정의되어 있는 프로퍼티에 정상적으로 접근할 수 있게 되었습니다. 이렇게 마우스를 가까이 해보면 프로퍼티 값의 타입도 잘 나타남을 알 수 있습니다.
let dog: {
name: string;
color: string;
} = {
name: "별이",
color: "brown",
};
프로퍼티의 타입이 문자열타입으로 같으면 이와 같이 지정해주면 됩니다. 이렇게 타입스크립트는 객체의 타입을 정의할 때 프로퍼티를 기준으로 객체의 구조를 정의하는 방식으로 타입을 정의합니다. 이러한 특징을 구조적 타입 시스템이라고 부릅니다.
◎ 특수한 프로퍼티 정의하기
⓵ 선택적 프로퍼티 (Optional Property)
let user: {
id?: number;
name: string;
} = {
id: 1,
name: "shyunu",
};
user = {
name: "홍길동", // ❌
}
다음과 같이 id가 아직 없고 이름만 있는 유저가 존재할 수도 있는데 이렇게 작성하게 되면 타입스크립트에서는 오류가 발생합니다. user는 id와 name 프로퍼티가 있는 객체인데 마지막 코드에서 name만 존재하는 객체를 할당하였기 때문입니다.
let user: {
id?: number; // ?를 사용하면 선택적 프로퍼티가 된다.
name: string;
} = {
id: 1,
name: "shyunu",
};
이와 같이 상황에 따라 특정 프로퍼티를 생략하도록 하고 싶다면 해당 프로퍼티를 선택적 프로퍼티로 만들어주면 됩니다. 프로퍼티의 이름 뒤에 ?를 붙여주면 선택적 프로퍼티가 됩니다. 물음표는 생략 가능한 선택적(Optional) 프로퍼티가 되었음을 의미합니다
⓶ 읽기전용 프로퍼티 (Readonly Property)
let config: {
readonly apiKey: string;
} = {
apiKey: "MY API KEY",
};
config.apiKey = "hacked"; // ❌
값이 절대 수정되어서는 안되는 변수가 있다면 프로퍼티의 이름 앞에 readonly 키워드를 붙이면 됩니다. apiKey 프로퍼티는 이제 읽기 전용 프로퍼티가 되었기 때문에 마지막 코드처럼 해당 프로퍼티의 값을 수정하려고 하면 에러가 발생합니다. 이를 통해 의도지 않은 프로퍼티의 수정을 방지할 수 있다는 장점이 있습니다.
출처) 한 입 크기로 잘라먹는 타입스크립트(TypeScript)_이정환
'📍 프로그래밍 언어 > TypeScript' 카테고리의 다른 글
[ TypeScript ] any, unknown, void, never : 헷갈리는 타입 한눈에 보기 (0) | 2024.12.18 |
---|---|
[ TypeScript ] 타입 설계: 타입 별칭, 인덱스 시그니처, 열거형 타입으로 코드 최적화하기 (0) | 2024.12.18 |
[ TypeScript ] 데이터 타입 (기본타입 / 원시타입 / 리터럴타입) (0) | 2024.12.18 |
[ TypeScript ] Hello TS World ! (@types/node, TSX) (0) | 2024.12.17 |
[ TypeScript ] 타입스크립트의 동작 원리 (0) | 2024.12.17 |