개인 학습 과정에서 작성한 markdown 문서로 잘못된 내용이 존재할 수 있습니다.
잘못된 내용 또는 개선 방안을 말씀해주시면 수정하겠습니다.
📝 TypeScript 기초 학습 (1)
TypeScript 학습을 위해 공식문서를 참고하여 읽고 정리한 내용입니다.
1. 배경
타입스크립트(TypeScript) 는 자바스크립트(JavaScript) 를 기반으로 한 확장된 언어로 타입스크립트에서는 자바스크립트의 모든 문법을 사용할 수 있다.
자바스크립트에서는 string, number, object 등 데이터 타입이 있지만, 변수에 직접 지정해주지 않고, 값을 넣을때마다 데이터 타입을 모두 담을 수 있다. 이런 특징은 변수 타입을 지정하지 않아도 되고 모든 타입의 값을 할당할 수 있어 좋을 수 있지만, 프로그래머가 의도하지 않은 오류(버그)가 발생할 확률이 굉장히 높아진다.
또한, 자바스크립트에서 코드에 오류가 있어도 우선 웹 브라우저상에서 실행이 되기 때문에 어떠한 부분에서 오류가 발생했는지 알기 힘든 경우도 많이 있다.
이런 자바스크립트의 단점을 보완하여 데이터 타입을 명확하게 명시하고 어느 부분에 오류가 있는지 알려주는 타입스크립트가 등장하게 되었다.
2. 설치 및 사용
npm install -g typescript
위의 명령어를 입력하여 타입스크립트를 전역으로 설치한다.
각 프로젝트에서만 필요에 의해 사용하는 경우 npx 와 같은 명령어를 사용하여 설치하면 된다.
사용방법은 간단하다.
- 확장자를 .js 가 아닌 .ts 로 파일을 생성한다.
- 코드 작성
- 명령어 입력
위의 명령어를 입력하면 타입스크립트 파일을 타입스크립트가 컴파일 하여 위의 파일과 같은 내용의 '파일명.js' 파일을 생성한다. (동일한 기능을 하는 자바스크립 코드로 컴파일을 해준다.)tsc 파일명.ts
- 컴파일 중 오류가 발생해도 타입스크립트는 오류는 명시해주지만, 컴파일을 진행시켜 자바스크립트 코드를 생성해준다. 그러나 오류가 발생했을때 자바스크립트를 생성하기를 원하지 않는 경우 --noEmitOnError 옵션을 사용한다.
tsc --noEmitOnError 파일명.ts
- 컴파일 중 오류가 발생해도 타입스크립트는 오류는 명시해주지만, 컴파일을 진행시켜 자바스크립트 코드를 생성해준다. 그러나 오류가 발생했을때 자바스크립트를 생성하기를 원하지 않는 경우 --noEmitOnError 옵션을 사용한다.
각종 컴파일러 옵션과 관련된 내용은 공식문서(TypeScript Handbook)을 번역하는 프로젝트의 깃허브 페이지에서 작성한 페이지에서 참고하면 좋다.
3. 개념 및 문법
1) 타입 추론 (Type Inference)
let a = 'hello';
a = 10;
기존 자바스크립트에서는 위와 같이 a 변수에 문자열 hello 값을 할당하여 사용하고 이후에 숫자형 10 을 넣어도 문제없이 할당하고 변수 a 를 사용할 수 있었다.
그러나 타입스크립트에서는 변수 a 를 hello 값을 할당하면 변수 a 는 문자열 변수로 타입을 추론하여, 앞으로 문자열 데이터만 할당할 수 있게 된다.
이 과정이 타입스크립트의 '타입 추론' 개념이다.
타입스크립트가 알아서 변수의 타입을 추론하여 그 타입에 맞게 사용할 수 있도록 검사하는것이라고 생각하면 이해하기 쉽다.
이후에 타입을 명시하는 방법을 배우지만, 타입스크립트가 타입을 명시하지 않아도 올바른 타입을 알아낼 수 있다면, 굳이 타입을 명시하지 않는 것이 가장 좋다.
2) 타입 명시
function hello(id: number, text: string, date: Date) {
console.log(`Hello ${id}, ${text} - DATE : ${date}`);
}
위의 코드와 같은 방식으로 명시적으로 데이터의 타입을 표기할 수 있다.
위 함수의 파라미터 중 id 는 숫자형의 데이터만, text 는 문자열, date 는 날짜형의 데이터만 올 수 있다는 것을 의미한다.
3) 타입 종류
- string : 문자열
- number : 숫자형 (정수, 실수)
- boolean : 불린값
- number[] 또는 Array<number> : 숫자형 배열
- string[] 또는 Array<string> : 문자형 배열
- any : 모든 타입
4) 타입 표기 방식
변수
let person: string = 'unho';
위 방식처럼 명시적으로 타입의 형태를 지정할 수 있으나, 타입의 추론으로 타입의 형태를 어차피 알 수 있기 때문에 굳이 명시적으로 표기하지 않아도 괜찮음
함수의 매개변수 (파라미터)
function person(name: string, age: number) {
// 생략
}
위의 코드처럼 함수의 매개변수 (파라미터)에 데이터형을 지정할 수 있다.
함수의 반환값
function person(name: string, age: number): string {
return `이름 : ${name}, 나이 : ${age}`;
}
위의 코드처럼 함수의 매개변수 목록 뒤에 함수의 반환 데이터의 타입을 명시할 수 있다.
함수가 아무것도 반환하지 않는 경우 void 사용
이 또한 타입 추론으로 타입스크립트는 반환 데이터의 타입을 알 수 있어 생략이 가능하다.
객체
function person(info: {name: string, age: number}) {
// 생략
}
객체 안의 값들도 타입을 지정할 수 있다.
객체의 각 프로퍼티를 구분할 때 , 또는 ; 를 사용할 수 있다.
객체의 프로퍼티의 타입 표기 또한 선택사항인데, 표기하지 않으면 any 타입으로 간주한다.
옵션 타입
함수의 매개변수에서 타입을 지정하면 모든 매개변수가 모두 들어와야하는데 상황에 따라 몇개가 넘어가지 않는 경우가 존재한다. 그럴때 옵셔널로 지정하여 그 매개변수 값이 들어올수도 안들어올수도 있다는 사실을 알릴 수 있다.
function person(info: {name: string, age?: number}) {
//생략
}
위의 코드에서는 info 라는 객체의 매개변수에서 age 프로퍼티의 값은 있을 수도 있고, 없을 수도 있음을 의미한다.
유니언 타입
유니언 타입은 서로 다른 두 개 이상의 타입을 사용해서 만드는 것인데, 정의된 타입 중 어떤 하나를 타입으로 가질 수 있다.
function person(age: string | number) {
// 생략
}
위의 코드처럼 | 를 사용하여 매개변수 age 는 문자열 또는 숫자형의 데이터 타입을 가질 수 있다.
배열 또는 객체를 가지려 하는 경우에는 오류가 발생
🔥 주의 사항
유니언 타입을 사용하는 경우, 특정 데이터 타입에서 사용하는 메서드를 사용할때 오류가 발생한다.
따라서 조건문으로 데이터 타입에 따라 구분하여 처리를 해주어야 한다.
아래의 경우처럼 문자열에서만 사용 가능한 toUpperCase() 메서드를 사용할 경우, 문자열일때만 사용하도록 조건문 분기를 해주어야 한다.
단, 두개의 데이터 타입이 모두 가지고 있는 공통된 메서드라면 조건 분기 없이 사용 가능
function person(age: string | number) { if (typeof age === 'string') { console.log(age.toUpperCase()); } else { console.log(age); } }
타입 별칭
같은 객체를 여러 함수에서 사용할 경우, 매번 객체 프로퍼티의 데이터 타입을 명시하는것은 너무 반복적인 작업이다.
이런 반복없이 한번 명시한 내용을 재사용 하기 위해서 타입 별칭이 존재한다.
type Info = { // 객체
name: string;
age: number;
}
type StringOrNumber = string | number; // 유니온 타입
function person(info: Info) {
// 생략
}
function personTwo(info: Info) {
// 생략
}
위의 코드처럼 재사용하여 사용이 가능하다.
인터페이스
interface Info {
name: string;
age: number;
}
function person(info: Info) {
// 생략
}
별칭과 아주 유사하다. 그러나 별칭은 새로운 프로퍼티를 추가하기 어려운 반면, 인터페이스는 추가 프로퍼티를 넣기 수월하다.
추가 관련된 사항은 공식문서 참고
타입 단언
개발자가 이미 타입의 종류에 대해 잘 알고 있는 경우 타입 단언을 사용하면 좀 더 구체적으로 명시 가능
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
자세한 사항은 공식문서 참고
리터럴 타입
프로그래밍을 하다보면 어떤 변수에는 특정 값만 들어오기를 원하는 경우가 있다. 이럴때 리터럴 타입을 사용하면 편리하다.
interface Info {
gender: string;
}
function person(name: string, age: 28 | 29 | 30, text: 'hello' | 'hi', info: Info | 'nothing') {
// 생략
}
위 함수의 매개변수 중 age 는 28, 29, 30 값만 들어올 수 있고, text 는 hello 또는 hi 값만 받을 수 있다.
info 는 인터페이스의 객체에서 gender 프로퍼티를 받거나 nothing 이라는 문자열만 받을 수 있다.
리터럴 타입에서 하나의 값만 들어오게 설정하고 싶은 경우 아래와 같이 사용할 수 있다.
const person = { city: 'seoul', gender: 'male' };
그러나 이렇게 사용하면 city 는 string 으로 타입을 추론하지 'seoul' 값만 받는다고 추론 하지는 않는다.
따라서 문제를 해결하기 위해서는 두가지 방법이 존재한다.
- 둘 중에 한 위치에 타입 단언을 추가하여 추론 방식을 변경한다.
수정 1 - person.city 는 항상 리터럴 타입인 seoul 이고, 해당 프로퍼티는 다른 값이 들어오는 것을 방지하겠다.// 수정 1 const person = { city: 'seoul' as 'seoul', gender: 'male' }; // 수정 2 inputData(person.city as 'seoul', person.gender);
수정 2 - 어떤 이유인지, person.city 가 'seoul' 값을 가진다는 사실을 알고 있다. - as const 사용하여 객체 전체를 리터럴 타입으로 변환한다.
as const 는 일반적인 const 와 유사하게 작동하여 해당 객체의 모든 프로퍼티에 string 또는 number와 같은 보다 일반적인 타입이 아닌 리터럴 타입의 값이 대입되도록 보장한다.declare function inputData(city: 'seoul', gender: string): void; const person = { city: 'seoul', gender: 'male' } as const; inputData(person.city, person.gender);
열거형 (Enum)
열거형(Enum) 이란, 연관된 변수들을 함께 묶어서 표현 할 수 있는 수단이다.
리터럴과 유사하다.
enum GenderType {
Male;
Femal;
}
function person(name: string, gender: GenderType) {
// 생략
}
person('unho', GenderType.Male);
위의 코드를 통해 생성된 자바스크립트 코드를 보면, enum 에 관련된 코드가 생성이 되는데 선택할 수 있는 값들은 순차적으로 Male 은 숫자 0의 값을, Female 은 숫자 1의 값을 가지게 되는데, 이러한 열거형을 숫자 열거형이라 한다.
enum GenderType {
Male = 'male';
Femal = 'female';
}
function person(name: string, gender: GenderType) {
// 생략
}
person('unho', GenderType.Male);
위의 코드를 사용하는 경우에는 숫자 열거형이 아닌 문자 열거형으로 생성된다.
숫자 열거형은 입력되는 값이 추가될때마다 숫자가 자동 증가하지만, 문자 열거형은 숫자가 자동 증가하지 않는다.
그러나 문자 열거형에서는 직렬화 이점이 있어 열거형 멤버 자체의 이름과 독립적으로 코드가 실행될때 읽기 쉬운 값을 제공한다.
참고 자료
- 유튜브
'공부 및 정리 > 프론트엔드' 카테고리의 다른 글
함수형 프로그래밍 (0) | 2022.03.14 |
---|---|
[React with Typescript] React에 Typescript 적용시키기 (1) (0) | 2022.01.08 |
[CSS] CSS-in-CSS vs CSS-in-JS (0) | 2022.01.06 |
[React] React Router v6 기초 학습 (0) | 2021.12.30 |
[React] 클래스형과 함수형 컴포넌트 (0) | 2021.12.29 |
댓글