
JavaScript는 기본이고 이제는 TypeScript가 중요해지고 있다.
JavaScript가 근간이고 TypeScript가 그 위로 붙었다. 확장된 버전이라고 할 수 있다.
JavaScript는 원래 브라우저에서만 쓰이는 언어였다. 하지만, 현재의 JavaScript는 브라우저에서 동작하는 것 뿐만 아니라 웹 애플리케이션 개발 과정에서 모든 곳에서 쓰일 수 있게 되었다. 코드가 광범위하게 쓰이면서 한계가 보이기 시작했다.
동적 타입 언어라는 한계가 있다. 동적 타입 언어란 변수의 타입을 런타임(실행 시간)에 결정하는 언어다. 개발자가 코드를 작성할 대 변수의 타입을 명시적으로 선언하지 않아도 되는 언어다. 변수에 값을 할당하는 과정에서 해당 변수의 타입이 자동으로 결정된다.
따라서, 할당된 값에 따라 타입이 동적으로 바뀌기 때문에 런타임에 타입 오류를 발견하기 어렵다. 이러한 한계를 보완하기 위해 TypeScript가 생겼다.
let x; // 현재 타입은 undefined
x = 1; // 현재 타입은 숫자(Number)
x = "Hello world!" // 현재 타입은 문자열(String)
TypeScript같은 것을 정적 타입 언어라고 한다.
변수의 타입을 컴파일 단계에서 명시적으로 선언해서, 런타임 오류를 줄일 수 있다.
TypeScript는 브라우저에서 읽지 못하는 언어다.
코드 에디터에서 세팅하여 사용해야 한다.
Typescript는 Javascript로 번들링 된다.
결국 브라우저에는 JavaScript 파일이 올라간다.
$ npm install typescript --save-dev
프로덕션(production) 단계에서 빌드 시 필요없는 라이브러리고,
개발(develop) 단계에서 코드 작성시에 도움을 주는 라이브러리기 때문에
--save-dev로 설치를 해준다.
tsconfig.json 설정
//tsconfig.json
{
"compilerOptions": {
"target": "es6", // ECMAScript의 버전을 타겟해서 변환해줄거다.
"module": "commonjs", // 번들해서 컴파일할 때, 모듈 시스템 설정
"sourceMap": true, // 컴파일러가 컴파일 과정에서 소스 맵 파일을 생성할 지 여부.
"outDir": "./dist" // 컴파일된 파일들이 위치하는 곳
},
"include": [ // 컴파일 대상으로 삼을 파일들을 지정하는 옵션
"src/**/*" // 각 파일을 따로 적어줘도 되지만,
] // 이렇게 적으면 모든 하위 디렉토리에 있는 모든 .ts 파일들을 대상으로 지정한다.
}
npx tsc --project tsconfig.json
- TypeScript 코드 작성: TypeScript 파일(
.ts확장자)에 코드 작성.- TypeScript 컴파일: TypeScript 컴파일러(
tsc)를 사용하여 TypeScript 파일들을 JavaScript로 변환.- 번들링 설정: Webpack을 사용하여 프로젝트에 필요한 설정을 구성.
- 번들링 실행: Webpack이 TypeScript로 컴파일된 JavaScrip 파일들을 읽어들여 하나의 번들 파일로 묶어준다
- 번들 파일 사용: 생성된 번들 파일을 HTML 파일에 연결하여 웹 애플리케이션에서 사용.
- Boolean
let isTrue: boolean = true;
- Number
let number1: number: 1;
- String
let str: string = "Hello world!"
- Array
// 첫번째 방법 let alphabet: string[] = ["a", "b", "c"] // 두번째 방법 let alphabet: Array<number> = [1, 2, 3] // 두번째 방법은 제네릭 배열 타입을 사용한 것이다. 배열 타입은 기본적으로 하나의 타입만 작성하게 되어 있다
- Tuple
요소의 타입과 개수가 고정된 배열 표현let car: [string, number, boolean] = ["gv70", 6000, true] // 고정되어있기 때문에 다른 타입으로 그냥 변경하면 에러가 발생한다. // ex) car[1].toString() ==> // error
- Object
let obj: object = {}; // `object 타입은 모든 객체를 수용하는 타입이기 때문에 어떤 프로퍼티라도 추가할 수 있다. 좋은 방법 X` let car: { name: string, price: number, isOption: boolean } = { name: "gv70" price: 6000, isOption: true }
- Any
알지못하는 타입일수도 있다. 타입 검사를 하고 싶지 않을 때는any타입을 사용하여 건너뛴다.let obj: object = {}; obj = "hello" // 에러 발생 let donno:any = 1; donno = "i know" // 변경 가능데이터에서 타입의 일부만 알고 전체는 알지 못할 때 유용하다.
let list = [1, 5, "3", false, {a:1, b:2}, ["hello"]]; list[2] = 3 // string 타입을 number 타입으로 재할당 가능.
function add(x: number, y: number): number {
return x + y;
}
매개변수의 타입은 각자 옆에 바로 적어주고, 이 함수에 리턴값에 해당하는 타입은 괄호 뒤에 붙여준다.
리턴값을 작성하지 않아도 TypeScript 컴파일이 스스로 판단해서 타입을 넣어준다. 이것을 타입 추론이라고 한다. 이로 인해, 리턴값은 생략이 가능하다.
let greeting = ( firstName: string, lastName?: string = "김" ): string => {
return `안녕하세요, ${firstName} ${lastName}님`
}
매개변수는 개수가 맞아야 제대로 함수가 동작한다.
예외가 있는데 그것이 바로 매개변수에 기본값을 설정하는 것과 선택적 매개변수
?를 붙여 이 변수가 안 들어 올수도 있다는 가능성을 뜻한다.TypeScript는 연산자를 이용해 타입을 정할 수 있다. ||, && 같은 연산자를 이용해서 표현한다.
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}`)
}
}
any를 안쓰고 왜 굳이 연산자를 넣어서 표현했을까?
장점으로는 코드 가독성이 좋고, 이해하기기 쉽고, 타입 추론이 가능해 타입과 관련된 API를 자동완성으로 얻어낼 수 있다.
interface GV70 {
owner: string,
isOption: boolean
}
interface Car {
owner :string,
carYear: number
}
function askSomething(somecar: GV70 | Car) {
console.log(somecar.owner);
}
인터페이스에서 가져온 타입을 사용할 때, 공통 프로퍼티인 owner에만 접근할 수 있다.
만약 나머지 프로퍼티에도 접근하고 싶다면 타입 가드를 사용해야 한다.
function askSomething(somecar: GV70 | Car) {
if ("isOption" in somecar) {
// somecar는 GV70 타입이다.
console.log(somecar.isOption);
} else {
// somecar는 Car 타입이다.
console.log(somecar.carYear);
}
}
askSomething( { owner: "홍길동", isOption: true } );
askSomething( { owner: "홍길동", carYear: 1 } )
in 연산자를 사용해 프로퍼티에 객체 내에 존재하는지 여부를 검사한다.
둘 이상 타입을 결합하여 새로운 타입을 만드는 방법. & 연산자 사용.
interface GV70 {
owner: string,
isOption: boolean
}
interface Car {
owner :string,
carYear: number
}
function askSomething2(somecar: GV70 & Car) {
// 타입 가드 사용하지 않아도 모든 프로퍼티 사용가능
console.log(somecar.owner);
console.log(somecar.isOption);
console.log(somecar.carYear);
}
// 인터렉션 타입으로 결합 시, 전달인자를 선택해서 보내지 못한다.
askSomething2({ owner: "홍길동", isOption:true, carYear: 1 })