불과 1 2년 전만 해도 TypeScript사용은 취업 시장에서 우대사항 수준이었지 필수적인 사항은 아니었다고 한다. 하지만 최근들어 취업시장에서 js를 다루는 개발자라면 반 필수적으로 TypeScript사용자를 원하고 있는 추세이다. 오늘은 TypeScript 첫번째 시간으로 프로젝트 환경 구성 방법과 타입, 함수, 연산자 활용에 대해 학습 하였다.
npm init -y
프로젝트를 npm init -y
명령어를 통해 프로젝트를 초기화 시킨다.
npm install typescript --save-dev
프로젝트에 TypeScript설치 후 루트 디렉토리에 tsconfig.json
파일을 생성한다. tsconfig.json
는 TypeScript파일을 JS파일로 변환할 때 어떤방식으로 변환할것인지 설정에 대한 커스텀을 하는 용도이다.
{
"compilerOptions": {
"target": "es6", // 어떤 버전의 자바스크립트로 바꿔줄 것인지 작성.
"module": "commonjs", // JS파일 간 import 문법을 구현할 때 어떤 문법을 사용할 것인지 작성.
"sourceMap": true, // 빌드 시 map 파일을 생성할 것인지에 대한 여부.
"outDir": "./dist" // JS 파일의 아웃풋 경로.
},
"include": [
"src/**/*"
]
}
TypeScript에서는 타입에 관한 부분을 엄격하게 지정을 해 지정한 타입 이외의 타입은 들어올 수 없게 한다. 그로인해 타입 관련 에러들을 잡아줄 수 있는 장점이 있다.
기본적인 참, 거짓 값.
let isShow: boolean = true;
let isDone: boolean = false;
정수와 실수 구분 없이 Number타입 하나로 표기.
let number1: number = 5;
let number2: number = 0.7;
'', "", `` 이 들어간 문자타입을 string으로 지정 해준다.
let firstName: string = "kim";
배열타입은 기본적으로 하나의 타입만 작성하게 되어 있고 타입을 혼용해서 작성하는 것은 불가능 하다.
//첫 번째 방법
let items: string[] = ["apple", "banana", "grape"];
//두 번째 방법
let numberList: Array<number> = [4, 7, 100];
요소의 타입과 개수가 고정된 배열을 표현할 수 있다.
let user: [string, number, boolean] = ["kimcoding", 20, true];
접근한 요소의 타입과 다른 타입이면 에러가 발생한다. 이로인해 타입에러를 빠르게 확인 할 수 있다.
console.log(user[2].toString());
user[2]
의 요소는 boolean타입이기 때문에 에러가 발생한다.JS와 마찬가지로 원시 타입(number, string, boolean, undefined, null, symbol)이 아닌 타입을 뜻한다.
let obj: object = {};
TypeScript에서 object
타입은 모든 객체를 수용하는 타입이다. 별도의 타입을 지정해주지 않으면 any
타입으로 지정이 되는데 이는 TypeScript의 목적과는 달라지기 때문에 최대한 객체의 프로퍼티 타입들을 명시해 주는것이 좋다.
let user: {name: string, age: number} = {
name: "kimcoding",
age: 20
}
클라이언트에서 유저로부터 데이터 혹은 서드파티 라이브러리에서 들어오는 값과같이 개발자가 알지 못하는 타입을 받을때 타입검사를 거치지 않고자 할때 사용한다.
let maybe: any = 4;
any
타입을 사용하면 변수에 값을 재할당하는 경우 타입에 구애받지 않고 값을 재할당할 수 있다.
let obj: object = {};
//에러
obj = "hello";
let maybe: any = 4;
//정상적으로 동작
maybe = true;
그리고 any
타입은 타입의 일부만 알고있을시 유용하게 사용 가능하다.
let list: any[] = [1, true, "free"];
//any로 다루고 있기 때문에 index 1번째 요소가 boolean 타입이지만 number 타입으로 재할당할 수 있습니다.
list[1] = 100;
//named function
function add(x: number, y: number):number {
return x + y;
}
//arrow function
let add = (x: number, y: number): number => {
return x + y;
}
만약 함수에 리턴값이 없다면 void
를 사용해 작성.
let printAnswer = (): void => {
console.log("YES");
}
JS와 달리 매개변수의 개수에 맞춰 전달인자를 전달해야 한다.
let greeting = (firstName: string, lastName: string): string => {
return `hello, ${firstName} ${lastName}`;
}
//에러 발생.
greeting('coding');
//정상적으로 작동.
greeting('coding', 'kim');
//너무 많은 매개변수를 보내 에러 발생.
greeting('coding', 'kim', 'hacker');
매개변수의 초기값을 설정 할수도 있다. 이는 JS에서의 default parameter
와 같은 동작을 한다.
let greeting = (firstName: string, lastName: string ="kim"): string => {
return `hello, ${firstName} ${lastName}`;
}
//정상적으로 작동.
greeting('coding');
//정상적으로 작동.
greeting('coding', undefined);
//너무 많은 매개변수를 보내 에러 발생.
greeting('coding', 'kim', 'hacker');
선택적 매개변수를 원한다면 매개변수의 이름 끝에 ?
를 붙여준다.
let greeting = (firstName: string, lastName?: string): string => {
return `hello, ${firstName} ${lastName}`;
}
//정상적으로 작동.
greeting('coding');
//정상적으로 작동.
greeting('coding', 'kim');
//너무 많은 매개변수를 보내 에러 발생.
greeting('coding', 'kim', 'hacker');
둘 이상의 타입을 합쳐서 만들어진 새로운 타입이다. |
연산자를 사용하고 JS의 ||
과 같은의미의 타입이다.
function printValue(value: number|string): void {
if (typeof value === "number") {
console.log(`The value is a number: ${value}`);
} else {
console.log(`The value is a string: ${value}`);
}
}
printValue(10); // The value is a number: 10
printValue("hello"); // The value is a string: hello
유니온 타입인 값이 있으면 유니온에 있는 모든 타입에 공통인 멤버만들에만 접근할 수 있다.
interface Developer {
name: string;
skill: string;
}
interface Person {
name: string;
age: number;
}
function askSomeone(someone: Developer | Person) {
console.log(someone.name);
}
위와 같이 두 인터페이스를 적용하고 함수에서 활용하였을때 Developer
와 Person
의 공통 프로퍼티인 name
에만 접근할 수 있다. 만약 다른 프로퍼티에도 접근하고 싶다면 타입 가드를 사용해야 한다.
타입가드
특정 코드 블록에서 타입의 범위를 제한해 해당 코드 블록 안에서 타입 안정성을 보장 해준다.
function askSomeone(someone: Developer | Person) {
// in 연산자 : 타입스크립트에서 객체의 속성이 존재하는지를 체크하는 연산자
// in 연산자는 객체의 속성 이름과 함께 사용하여 해당 속성이 객체 내에 존재하는지 여부를 검사
if ('skill' in someone) {
console.log(someone.skill);
}
if ('age' in someone) {
console.log(someone.age);
}
}
in
연산자는 객체의 프로퍼티 이름과 함께 사용되며 해당 프로퍼티가 객체 내에 존재하는지 여부를 검사한다.
인터섹션(Intersection) 타입은 둘 이상의 타입을 결합해 새로운 타입을 만드는 방법으로 $
연산자를 사용해 표현한다. 인터셉션 타입은 하나의 단일 타입으로 표현할 수 있기 때문에 타입가드가 불필요 하다.
interface Developer {
name: string;
skill: string;
}
interface Person {
name: string;
age: number;
}
function askSomeone(someone: Developer & Person) {
console.log(someone.age);
console.log(someone.name);
console.log(someone.skill);
}