TypeScript
는 기존의 JavaScript
를 더 안전하게 사용할 수 있도록 Type
관련된 여러 기능들이 추가된 언어이다.
Tpye 이 추가되면서 좀 더 엄격한 문법이 적용되지만 컴파일 과정에서 에러를 잡아내므로
런타임 환경에서 안정적이고 버그 발생 가능성을 낮출 수 있다. 😎
대부분의 프로그래밍 언어로 작성된 코드들은 컴파일
과정을 거쳐 컴퓨터가 이해할 수 있는 바이트 코드
로 변환되어 실행된다.
컴파일 과정을 살펴보면, 프로그래밍 언어는 바이트 코드로 변환전 AST(추상 문법 트리)
로 변환되어진다. 🤓
TypeScript 는 이 시점에 타입 검사를 실행한다.
타입에러가 발생하는 경우
컴파일 에러를 일으켜 실행을 종료하고 에러가 없는 경우
JavaScript 코드로 변환된다. 😀
💡 즉, TypeScript 는 컴파일 과정에서 타입 검사를 함으로써 런타임에 발생하는 버그를 사전에 방지할 수 있다.
tsconfig.json
파일에 TypeScript 컴파일 옵션을 설정 할 수 있다. 📝
{
"compilerOptions":{
// 컴파일 결과 생성되는 자바스크립트 버전 설정
"target": "ESNext", // 최신버전
// 모듈 시스템(import, export) 을 설정
"module": "ESNext",
// 컴파일 결과 생성되는 자바스크립트 코드의 위치 설정
"outDir": "dist",
// 타입 검사의 엄격함 설정
"strict": true,
"moduleDetection": "force",
// 타입 정의파일 (.d.ts 확장자는 타입검사 생략 )
"skipLibCheck": true,
...
},
// 컴파일 할 TypeScript 범위를 설정한다.
"include": ["src"],
"exclude": ["node_modules"]
}
기본 타입
은 TypeScript 에서 자체적으로 제공하는 타입들을 말한다.
다양한 종류의 타입들이 존재하며 각각의 타입들은 부모, 자식 관계를 이루며 계층을 형성하게 된다.
원시타입
은 배열과 객체와 다르게, 한개의 값만 저장할 수 있는 타입들을 말한다.
// number
let num1: number = 123;
let num2: number = -123;
let num3: number = 0.123;
let num4: number = -0.123;
let num5: number = Infinity;
let num6: number = -Infinity;
let num7: number = NaN;
// string
let str1: string = "hello";
let str2: string = 'hello';
let str3: string = `hello`;
let str4: string = `hello ${str1}`;
// boolean
let bool1 : boolean = true;
let bool2 : boolean = false;
// null
let null1: null = null;
// undefined 타입
let unde1: undefined = undefined;
// 숫자 배열
let numArr: number[] = [1, 2, 3]
// 문자열 배열
let strArr: string[] = ["hello", "im", "jaehan"];
// 불리언 배열 ( 제내릭 선언 )
let boolArr: Array<boolean> = [true, false, true];
// 멀티 배열
let multiArr: (number | string)[] = [1, "hello"];
// 다차원 배열
let doubleArr : number[][] = [
[1, 2, 3],
[4, 5],
];
기존 배열 타입에서 길이를 지정해줄 수 있다.
let tup1: [number, number] = [1, 2];
let tup2: [number, string, boolean] = [1, "hello", true];
let tup3: [number, number] = [1, 2, 3]; // error!
주의사항
튜플 타입은 TypeScript 에서만 제공하는 타입으로, 컴파일 후 JavaScript 에서는일반 배열타입
으로 인식된다.
따라서push()
,pop()
을 이용해 고정된 길이를 무시하고 요소를 추가하거나 삭제될 수 있으니 주의가 필요하다.
회원 정보를 저장하는 이차원 배열이 있다고 가정해보자.
const users = [
["이름1", 1],
["이름2", 2],
["이름3", 3],
["이름4", 4],
];
사용자의 실수로 [5, '이름5']
와 같은 데이터가 등록하는 것을 방지하기 위해 아래와 같이 튜플 타입을 사용한다.
// 튜플 타입
const users: [string, number][] = [
["이름1", 1],
["이름2", 2],
["이름3", 3],
["이름4", 4],
[5, '이름5'], // error!!
];
// 타입 별칭
type User ={
id?: number; // optional property
name: string;
}
const user: User ={
name: 'jaehan'
}
optional property
를 사용하면 해당 값은 필수값이 아니기 때문에 선언하지 않아도 에러가 발생하지 않는다.
객체 내에 변경하면 안되는 속성이 있는 경우 property 앞에 readonly
를 붙여주면 된다.
type Config = {
readonly apiKey: string
}
const config: Config ={
apiKey: 'My API Key'
}
config.apiKey = '1234567' // error !!
기존 객체 타입에 key
와 value
의 타입만 정의함으로써 좀 더 유연하게 사용할 수 있는 문법이다.
type CountryCodes = {
[key: string]: string
};
let countryCodes: CountryCodes = {
Korea: "ko",
UnitedState: "us",
UnitedKingdom: "uk",
// (... 약 100개의 국가)
Brazil : 'bz'
};
// enum 타입 선언
enum Role {
Admin = 0,
User = 1,
Guest = 2,
}
const user1 = {
role: Role.Admin
}
const user2 = {
role: Role.User
}
const user3 = {
role: Role.Guest
}
데이터 타입을 모르는 경우 any
타입을 사용한다.
모든 타입을 허용하는 만큼, 사용에 주의를 해야한다. 🚨
( 런타임 에러 발생 가능성이 있음 )
let anyVar: any = 10;
anyVar = "hello";
anyVar = true;
anyVar = {};
// 함수타입
anyVar = () => {};
// 컴파일은 성공하지만 런타임 에러!!
// ( 함수에는 toUpperCase() 사용 불가 )
anyVar.toUpperCase();
anyVar.toFixed();
anyVar.a;
함수에서 반환하는 값이 없는 경우 사용한다.
변수에서도 사용이 가능하지만 undefined
값만 받기 때문에 거의 사용하지 않는다.
function func2(): void {
console.log("hello");
}