기존의 Javascript는 웹 브라우저에서만 사용 가능, 유연한 문법 및 버그 발생 가능성이 높았음
node.js 의 등장으로 자바스크립트의 런타임 (실행 환경 = 구동기) 의 등장으로 어디서든 자바스크립트 구동이 가능하게 됨
따라서 Javascript의 활용도 증가에 따른 버그 발생 가능성을 낮추기 위해 안정성을 추가한 Typescript 등장
2. 특징
타입 시스템
정적 타입 시스템 : 코드 실행 이전에 모든 변수의 타입을 고정적으로 결정함 (C, Java)
동적 타입 시스템 : 코드를 실행하고 나서 그때 그때마다 유동적으로 변수의 타입을 결정함 (Python, Javascript)
Javascript : 변수의 타입들을 코드가 실행되는 도중에 결정함 = 변수의 타입을 우리가 직접 정의하지 않음
단점 : 오류가 발생해도 실행이 되긴 함
타입스크립트는 동적 타입 시스템 + 정적 타입 시스템 : 변수의 타입을 실행 전에 결정하여 타입 오류를 실행 전에 검사하지만, 모든 변수에 타입을 일일이 지정할 필요 없음 = 점진적 타입 시스템 (Gradual Type System)
3. 동작 원리
Javascript 동작 원리
Typescript 동작 원리 : 타입 검사 후 Javascript 로 변환
4. 실행하기
5. 컴파일러 옵션
타입스크립트 설정 파일
npm i -g tsx
tsx src/index.ts
tconfig.json
{
//해당 버전의 js로 컴파일 파일이 생성됨
//ESNext : 자바스크립트 최신 버전
"compilerOptions": {
"target" : "ESNext",
//변환되는 자바스크립트의 모듈시스템
//js 코드가 각 상황에 따라 변경됨
"module" : "ESNext",
//컴파일 시 생성되는 자바스크립트 파일 위치 설정 가능
"outDir": "dist",
//true : 엄격한 타입 검사
"strict": true,
//임시로 null 을 넣을 수 있게 만든다 => false
//strict 옵션의 하위 옵션
"strictNullChecks": false,
//index.ts/hello.ts 와 같은 파일들이 독립된 모듈(공간)으로 받아들이도록 설정
//const a= 1 정의한 a 와 동일한 알파벳을 다른 파일에서도 변수로 이름지어서 사용 가능
//일일이 파일에 export {}; 를 작성하지 않아도 됨(컴파일되는 js파일에 알아서 작성됨)
"moduleDetection": "force",
//node20부터 반드시 표기
"skipLibCheck": true
},
//동시에 한번의 명령어로 컴파일 가능하도록
//즉 src 파일 아래의 모든 것을 컴파일함
"include": ["src"]
}
pakage.json에 “type” : “module” 추가해주기 (이렇게 해야 명령어 node dist/index.js 이렇게 실행할 수 있음)
//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 ${num1}`;
//boolean
let bool1: boolean = true;
let bool2: boolean = false;
//null
let null1: null = null;
//undefined
let unde1: undefined = undefined;
//허용 안됨 (타입이 다르므로)
// "strictNullChecks": false, 해야 엄격 검사 x, null 넣을 수 있음
//let numA: number = null;
//리터럴 타입
//리터럴 -> 값
let numA: 10 = 10;
//10이라는 값만 허용하므로 아래 코드는 오류난다
//numA = 12;
let strA: "hello" = "hello";
//let booA: true = false; //에러
배열과 튜플
//배열
let numArr: number[] = [1, 2, 3];
let strArr: string[] = ["hello", "im", "winterlood"];
let boolArr: Array<boolean> = [true, false, true];
//배열에 들어가는 요소들의 타입이 다양할 경우
let multiArr: (number | string)[] = [1, "hello"];
//다차원 배열의 타입을 정의하는 방법
let doubleArr: number[][] = [
[1, 2, 3],
[4, 5],
];
//튜플
//자바스크립트는 없으며, 타입스크립트만 있음
//길이와 타입이 고정된 배열
//자바스크립트로 컴파일해보면 배열로 변화되어 있음 -> push메소드 같은것 사용 가능
let tup1: [number, number] = [1, 2];
let tup2: [number, string, boolean] = [1, "2", true];
//따라서 자바스크립트의 배열이라고 생각하게 됨 -> 오류 발생 x
//사용에 주의해야 함
tup1.push(1);
tup1.pop();
tup1.pop();
tup1.pop();
//인덱스 순서가 중요할 때 값을 잘못 넣는 경우를 방지할 수 있음
const users: [string, number][] = [
["홍길동", 1],
["강감찬", 2],
["세종대왕", 3],
["박혁거세", 4],
/* [5, "이성계"], */
];
객체
//object
//object 에는 객체라는 정보만 가지고 있음=> user.id 로 해도
//user가 객체라는 것만 알지 안의 내용을 알지 못함
//객체 리터럴 타입을 활용해야 함
//객체의 구조를 기준으로 타입을 정함 : 구조적 타입 시스템 (property base type system)
let user: { id?: number; name: string } = {
id: 1,
name: "홍길동",
};
//선택적인 프로퍼티라면?
// 타입에 ? 를 추가한다. (있어도 되고 없어도 된다라는 의미)
//선택적 프로퍼티 = Optional property
user = {
name: "홍길동",
};
let dog: { name: string; color: string } = {
name: "돌돌이",
color: "brown",
};
//readonly 추가 : 값이 수정될 수 없게 함
let config: { readonly apiKey: string } = {
apiKey: "My API KEY",
};
//수정 불가
//config.apiKey = "hacked";
객체 Enum 타입
//enum 타입
//여러가지 값들에 각각 이름을 부여해 열거해두고 사용하는 타입
//enum은 자바스크립트로 컴파일될때 사라지지 않는다. (타입 정의와는 달리 안사라짐)
//enum은 컴파일 시 자바스크립트의 객체로 변환됨
enum Role {
ADMIN, //아무것도 넣지 않으면 기본 0으로 초기화, 이후 아래부터 1씩 증가함 (숫자를 넣으면 이후 값들도 기본 수에 1씩 증가함)
USER = 10, //숫자형 enum
GUEST,
}
enum Language {
korean = "ko",
english = "en",
}
const user1 = {
name: "홍길동",
role: Role.ADMIN, //0 <-관리자
language: Language.korean,
};
const user2 = {
name: "홍길동",
role: Role.USER, //1 <- 일반 유저
language: Language.english,
};
const user3 = {
name: "아무개",
role: Role.GUEST, // 2 <- 게스트
};
console.log(user1, user2, user3);
any와 unknown 타입
any는 타입 검사를 비활성화하지만, unknown은 더 안전해서 다른 타입에 할당하거나 사용하려면 명시적인 타입 확인 과정이 필요하다.
//any
//특정 변수의 타입을 우리가 확실히 모를 때
let anyVar: any = 10;
anyVar = "hello";
anyVar = true;
anyVar = {};
anyVar = () => {};
//anyVar.toUpperCase(); //any는 타입검사를 모두 통과하지만 런타임 시 오류남 => 가능한 사용하지 않는 게 좋다
//anyVar.toFixed();
let num: number = 10;
num = anyVar;
//unknown
let unknownVar: unknown;
unknownVar = "";
unknownVar = 1;
unknownVar = () => {};
//num = unknownVar; //any와 달리 불가
//unknownVar.toUpperCase(); //any와 달리 불가
//타입 정제 필요
if (typeof unknownVar === "number") {
num = unknownVar;
}
void와 Never 타입
//void
//void -> 공허 -> 아무것도 없다
//void -> 아무것도 없음을 의미하는 타입
function func1(): string {
return "hello";
}
function func2(): void {
console.log("hello");
}
let a: void;
//a =1; // 불가
//a="hello"; //불가
//a={};
//a = null; //strictNullCheck 꺼야 대입 가능
a = undefined;
//never
//never -> 존재하지 않는
//불가능한 타입
//아무것도 담을 수 없음
function func3(): never {
while (true) {}
}
function func4(): never {
throw new Error();
}
let b: never;
let anyVar: any;
//b = 1; //불가
//b = {}; //불가
//b = ""; //불가
//b = undefined; //불가
//b = null; //불가 -> strictNullCheck 꺼도 불가함 (아무것도 넣을 수 없음)
//b = anyVar; //불가