일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 컴퓨터공학 #Java #자바 #클래스 #객체 #인스턴스
- 컴퓨터공학 #자료구조 #스택 #c++ #알고리즘 #백준문제풀이
- 컴퓨터공학 #c #c언어 #문자열입력
- 잔
- BOJ #컴퓨터공학 #C++ #알고리즘 #자료구조
- HTML #CSS
- Today
- Total
영벨롭 개발 일지
[TypeScript] 타입 선언 및 종류 본문
📌 타입스크립트의 Type
타입스크립트는 자바스크립트의 타입(primitive, object types)을 그대로 제공하면서, 추가적으로 제공하는 타입들이 있습니다.
Primitive types | Object types |
boolean, number, string, null, undefined, symbol | function, array, object, classes |
추가 제공 타입 | |
tuple, enum, any, void, never, union, unknown |
📌 Type Annotation & Inference
✔️ Type Annotation
Type annotation 은 개발자가 직접 타입을 지정하는 것을 의미합니다.
일반 변수, 함수의 매개 변수(parameter), 객체 속성 등에 :TYPE 을 붙여 타입을 지정합니다.
let num: number = 1;
let obj: { name: string, age: number };
function func(a: number, b: number): number {
return a + b;
}
✔️ Type Inference
Type inference 는 타입스크립트가 알아서 타입을 추론하는 것입니다.
예를 들어 let num = 1; 과 같이 변수를 선언과 동시에 초기화하게 된다면, 타입스크립트는 변수 num 을 자동으로 number 타입으로 추론하게 됩니다.
let num = 1; // number 타입으로 추론함
let str = "hello world"; // string 타입으로 추론함
✅ Type annotation 이 꼭 필요한 경우!
타입스크립트가 타입을 추론하지 못하여 Type annotation 이 꼭 필요한 경우는 다음과 같습니다.
- any 타입을 리턴받는 경우
다음 예제를 보시면 JSON.parse 메소드는 any 타입을 리턴합니다. 이때 type annotation 을 하지 않은 coord1 역시 any 타입으로 지정됩니다.
const json = '{"x": 1, "y": 2 }';
const coord1 = JSON.parse(json); // any
const coord2: { x: number; y: number } = JSON.parse(json); // { x: number, y: number }
- 변수 선언을 먼저하고, 초기화를 나중에 할 경우
앞서 언급했듯 변수의 선언과 동시에 초기화를 할 경우 타입스크립트가 해당 변수의 타입을 추론합니다.
하지만 초기화를 나중에 할 경우, 타입을 추론하지 못하고 any 타입으로 지정됩니다.
let tmp1 = 1; // number
let tmp2;
tmp2 = 1; // any
- 변수에 대입될 값이 일정하지 않은 경우
다음과 같이 변수에 대입될 값이 일정하지 않은 경우에도 type annotation 이 꼭 필요합니다.
let tmp1 = 1;
tmp1 = false; // error
let tmp2: number | boolean = 1;
tmp2 = false;
📌 Boolean Type
boolean 타입은 참(true) 또는 거짓(false) 을 값으로 갖습니다.
let bool1: boolean
bool1 = true;
let bool2: boolean = false;
📌 Number Type
number 타입은 정수, 실수, 2진수, 16진수, 8진수, NaN, Infinity 등의 숫자를 값으로 갖습니다.
let num: number;
let integer: number = 1;
let float: number = 1.23;
let hex: number = 0xfff;
let binary: number = 0b010;
let octal: number = 0o123;
let inf: number = Infinity;
let nan: number = NaN;
📌 String Type
string 타입은 큰 따옴표(""), 작은 따옴표(''), ES6의 템플릿 문자열로 표현할 수 있습니다.
let str: string;
let str1: string = "a";
let str2: string = "b";
let str3: string = `${str1}${str2}c` + "d";
📌 Array Type
배열 타입은 두 가지 방법으로 선언할 수 있습니다.
- Type[]
- Array<Type>
또한 any 나 union 타입을 통해 여러 타입의 값을 요소로 가질 수 있습니다.
또한 readonly 또는 ReadonlyArray 를 사용하여 읽기 전용 배열을 생성할 수 있습니다. 읽기 전용으로 생성한 배열에 요소를 추가하거나 수정하는 연산을 진행할 경우 에러가 발생합니다.
// 한 가지 타입을 가지는 배열
let names1: string[] = ["John", "Kim"];
let names2: Array<string> = ["John", "Kim"];
// 여러 타입을 가지는 배열(유니언 타입 사용)
let arr1: (string | number)[] = [1, "John"];
let arr2: Array<string | number> = ["John", 1];
// 여러 타입을 단언 X
let someArr: any[] = ["John", 1, [], {}, false];
// 읽기 전용 배열 생성
let strArr: readonly string[] = ["A", "B"];
let numArr: ReadonlyArray<number> = [1, 2];
// strArr.push('C') // 컴파일 에러
// numArray[0] = 3; // 컴파일 에러
📌 Tuple Type
튜플은 배열의 서브타입입니다. 배열과 유사하지만, 크기와 요소의 타입 및 순서가 고정되어 있습니다.
튜플의 선언은 [ Type1, Type2, ... ] 와 같이 할 수 있습니다.
let tup: [string, number];
tup = ["a", 1];
tup = [1, 'a'] // error: 타입 불일치
tup = ['a', 1, 2]; // error: 크기 불일치
2차원 튜플은 다음과 같이 선언할 수 있습니다.
let tup1: [number, string][];
let tup2: Array<[number, string]>;
tup1 = [[1, "Hello"], [2, "World"]];
tup2 = [[1, "Hello"], [2, "World"]];
튜플의 타입 뿐만 아니라 값 자체를 고정시킬 수도 있습니다. (강한 타입)
이때 타입이 일치하더라도, 고정된 값이 아닌 값을 넣으면 에러가 발생합니다.
let tup: [1, string];
tup = [1, "Hello"]; // OK
tup = [2, "World"]; // Error
이때 유의할 점은 튜플이라 하더라도 push 메소드를 이용하여 값을 넣는 것은 허용됩니다.
let tup: [string, number];
tup = ["a", 1];
tup.push(2); // tuple 이라고 하더라도 push 메소드를 이용해서 값을 넣는 것은 허용!!!
📌 Enum Type
enum 타입은 값들의 집합을 명명하고 이를 사용하도록 만드는 자료형이라고 보면 됩니다. 이때 주의해야할 점은 enum 의 속성 값으로는 숫자와 문자열만 허용됩니다.
enum 타입은 배열의 인덱스와 같이 멤버들의 값을 0부터 차례대로 지정하는 특징을 갖고 있습니다.
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right, // 3
}
let dir: Direction;
dir = Direction.Up; // 0
dir = Direction["Down"]; // 1
let dirKey: string = Direction[0]; // 'Up'
하지만 이는 기본 값일 뿐, 개발자가 직접 값을 명시할 수 있습니다. 값을 변경한 부분부터 다시 1씩 증가하며 지정됩니다.
enum Direction {
Up, // 0
Down, // 1
Left = 100, // 100
Right, // 101
}
속성 값을 문자열로 지정할 경우, 자동 증가가 되는 숫자와 달리 모든 속성에 대해 값을 지정해주어야 합니다.
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
let dir1: Direction = Direction.Up; // "UP"
let dir2: Direction = Direction["Down"]; // "DOWN"
✅ enum 과 객체의 차이점
- 객체는 코드내에서 새로운 속성을 자유롭게 추가할 수 있지만, enum 은 선언할 때 이후에 변경 불가
- enum 의 속성값으로는 문자열과 숫자만 허용됨
📌 Object Type
자바스크립트와 마찬가지로 타입스크립트에서도 객체, 배열, 함수까지 object 타입에 포함됩니다.
let obj: object = {};
let arr: object = [];
let func: object = function() {};
let date: object = new Date();
이처럼 여러 타입이 object 타입으로 인식되기 때문에, 다음과 같이 object 타입에 객체값을 주고 속성을 조회할 경우 에러가 발생합니다. 이는 object 타입에 id 속성이 없음으로 인식되기 때문입니다.
const obj: object = { id: 1, title: "hello" };
console.log(obj.id); // Error
따라서 object 타입이 아닌, 지정하고자 하는 객체의 속성들에 대한 타입을 개별적으로 지정하여 사용해야 합니다.
let obj: { id: number; title: string };
obj = {
id: 1,
title: "hello",
};
📌 Union Type
2개 이상의 타입을 지정하고자 할 때 사용하는 타입으로, | (파이프) 기호를 통해 타입을 구분합니다.
( Type1 | Type2 | ... ) 과 같이 유니온 타입을 지정합니다.
let union: string | number;
union = 1;
union = "a";
let arr: (string | number)[] = ["Hello", 1, "World"];
📌 Any Type
any 타입은 모든 타입에 대해 허용한다는 의미를 가집니다. 알지 못하는 타입을 표현할 때 유용하게 사용됩니다.
let any: any = "abc";
any = 1;
any = [];
let any2: any = any;
📌 Unknown Type
unknown 타입은 any 타입과 같이 모든 데이터 타입을 허용합니다. 하지만, 다른 변수의 값으로는 할당해줄 수가 없습니다.
let un: unknown = false;
let bool: boolean = un; // error
let value: unknown = "Hello";
let str = value;
console.log(str.length); // error
이때 타입 단언을 사용하여 unknown 타입의 변수를 다른 변수의 값으로 할당할 수 있습니다.
let un: unknown = false;
let bool: boolean = un as boolean; // OK
let value: unknown = "Hello";
let str = value as string;
console.log(str.length); // OK
✅ any와 unknown 의 차이점
any: 모든 타입 허용, 타입 검사를 느슨하게 한다.
unknown: 모든 타입 허용, 타입 검사를 엄격하게 한다.
예를 들어, number 타입으로 정의된 변수 num 으로부터 num.length 출력하는 코드를 실행하게 되면 에러가 발생합니다. 이는 number 타입에 length 프로퍼티가 존재하지 않기 때문에 발생하는 오류입니다.
let num: number = 10;
console.log(num.length); // Error: 'number'형식에 'length' 속성이 없습니다.
이를 number 타입이 아닌, any 타입으로 선언하는 경우 에러가 발생하지 않고 num.length 에 대해 undefined 를 출력하게 됩니다.
타입스크립트는 any 타입에 대해 타입 검사를 업격하게 하지 않기 때문에 개발자 입장에서 문제가 없는 코드이지만, 실제 애플리케이션에서 문제가 발생할 수 있습니다.
let num: any = 10;
console.log(num.length); // undefined
반대로 unknown 타입은 '모른다'의 의미가 강합니다. 할당된 값이 어떤 타입인지 모르기 때문에 함부로 프로퍼티나 연산을 할 수 없습니다.
let num: unknown = 10;
console.log(num.length); // Error: 'unknown' 형식에 'length' 속성이 없습니다.
📌 Null / Undefined Type
기본적으로 null 과 undefined 는 다른 모든 타입의 하위 타입임으로, 아무 타입에 할당할 수 있습니다.
이때 주의해야할 사항은 tsconfig.json 파일의 컴파일 옵션으로 "strictNullChecks": false 옵션을 설정해주어야 합니다.
- strictNullChecks: true
- 모든 타입은 null, undefined 값을 가질 수 없음. (가지려면 Union type 사용)
- any 타입은 null, undefined 값을 가질 수 있음.
- void 타입은 undefined 값을 가질 수 있음.
- strictNullChecks: false
- 모든 타입은 null, undefined 값을 가질 수 있음.
//"strictNullChecks": false 옵션 줘야함
let tmp1: number = undefined;
let tmp2: string = null;
let tmp3: { a: 10; b: false } = undefined;
let tmp4: any[] = null;
let tmp5: undefined = null;
let void1: void = null;
let void2: void = undefined;
📌 Void Type
void 타입은 어떤 타입도 존재할 수 없을 나타냅니다. 보통 반환 값이 없는 함수의 반환 타입을 표현하기 위해 사용됩니다.
변수를 void 타입으로 선언했을 경우, undefined 값만이 허용됩니다. 이때 strictNullChecks 옵션을 false 로 줬을 경우 null 값도 허용됩니다.
let void1: void = null; // strictNullChecks: false 일 경우 허용
let void2: void = undefined;
function greeting(): void {
console.log("hi");
} // 실제로는 undefined 이지만 void 가 아닌 undefined 로 지정하면 에러가 남
const hi = greeting(); // undefined
📌 Never Type
never 타입은 절대로 발생할 수 없는 타입을 나타낼 때 사용합니다. 어떠한 일이 절대로 일어나지 않을 것이라고 확신할 때 유용합니다.
주로 항상 에러를 발생시키거나, 리턴 값을 절대로 내보내지 않는(무한 루프) 함수의 리턴 타입으로 사용됩니다.
function throwError(): never {
throw new Error("error");
}
function keepProcessing(): never {
while (true) {
console.log("hi");
}
}
'Programming Language > TypeScript' 카테고리의 다른 글
[TypeScript] 타입 단언과 타입 가드 (Type Assertions & Guard) (0) | 2024.01.16 |
---|---|
[TypeScript] 타입스크립트의 Generics (0) | 2023.12.27 |
[TypeScript] Call Signature 와 Index Signature (0) | 2023.12.26 |
[TypeScript] Type Alias VS Interface (2) | 2023.12.26 |
[TypeScript] TypeScript 란? (0) | 2023.12.23 |