TypeScript 는 일종의 JavaScript 이다. JavaScript + Type 이 붙은 꼴로 상위 확장한 컴파일 언어이다. 동적 타입의 인터프리터 언어인 자바스크립트는 오류 발견이 있지만, 타입스크립트는 정적타입의 컴파일언어로 자바스크립트 코드로 변환해준다. 코드 작성 단계에서 타입을 체크해서 오류를 확인할 수 있고 미리 타입을 결정하기 때문에 실행속도가 빠르다. 이것이 타입스크립트를 사용하는 큰 이유가 아닐까 생각한다.
예를 들면,
function sum(a,b) { return a + b; }
위 함수는 두 개의 숫자를 인자로 받아 합계를 리턴하는 함수를 의도했을 것이다. 하지만 코드상으로는 어떤 타입이든지 인자로 들어갈 수 있지만, 전달인자나 반환값의 타입은 명확하지 않아서 오류를 쉽게 범할 수 있다.
function sum(a: number, b: number){ return a+b; }
정적타입으로 전달인자의 타입을 명확히 해주면 당연히 반환값 또한 명확해진다. 이미 인자로 number 타입만 전달되기 때문에 컴파일 단계에서 쉽게 오류를 파악할 수 있다.
이런 명시적인 타입 지정은 개발자의 의도를 명확하게 코드로 기술할 수 있고, 코드의 가독성을 높이고 예측할 수 있게 하며 디버깅이 쉬워진다.
npm init -y
npm install typescript --save-dev
: package.json
파일에서 개발단계에서 패키지를 모아놓는 패키지인 devDepndencies
속성에 typescript
가 설정된다.
//tsconfig.json
//compilerOptions 내의 속성은 자유롭게 커스텀 할 수 있습니다.
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"sourceMap": true,
"outDir": "./dist"
},
"include": [
"src/**/*"
]
}
vscode
는 기본적으로 typescript에 대한 intellisense 를 지원하는데, 이 intellisense가 .ts
파일을 인식하는 방법을 제어하기 위해 tsconfig.json
을 작성해야한다. 그리고 tsc
가
tsconfig.json
파일은 프로젝트를 컴파일하는데 필요한 루트 파일과 컴파일러 옵션을 지정한다.
cimpilerOptions
속성은 생략될 수 있고, 생략이 되면 컴파일러의 기본값이 사용된다.
target
은 타입스크립트 파일을 어떤 버전의 자바스크립트로 바꿔줄지 정하는 부분module
은 자바스크립트 파일간 import 문법을 구현할 때 쓸 문법 결정 sourceMap
은 컴파일된 js 와 ts 간의 맵핑의 유무 결정outDir
은 모든 파일을 하나의 파일로 합쳐서 출력할 경우 지정하는 파일명inlcude
속성은 프로그램에 포함할 파일 이름이나 패턴을 배열로 지정한다.타입을 직접 지정하여 컴파일 시점에서 에러를 쉽게 잡아낼 수 있다.
let 변수명: 타입 = ___ ;
//숫자형
let oneTwoThree: number = 123;
//문자열 - 큰, 작은 따옴표, 백틱 사용
let code: string = 'helloWorld!';
//boolean
let isDone: boolean = true;
//배열
let arr1: number[] = [1,2,3];
let arr2: Array<number> = [1,2,3];
let arr3: Array<string> = ['one', 'two', 'three'];
//튜플 - 요소의 타입과 개수가 고정된 배열로 표현
let tupple: [string, number] = ['hello', 5];
//객체
let user: {name: string, age: number} = {
name: 'jiwon', age: 26
}
//Any - 어떤 타입도 허용하는 실드 해제 문법
// 타입을 미리 정하기 애매할 경우 사용
// 타입관련 버그 생길 경우 추적하기 어려운 단점
let list: any[] = [1,true, "free"];
list[1] = 100; // 값 재할당 가능
함수 작성시 매개변수의 타입과 반환타입을 명시해야한다.
매개변수의 타입만 명시해주고 반환타입은 명시하지 않아도 타입 추론 기능으로 반환값을 유추가능하다.
//매개변수 O, 반환 O => 타입 추론 기능 x
function concat(a: string, b: string): string {
return a+b;
}
//매개변수 O, 반환 X => 타입 추론 기능 O
let concat = (a: string, b: string) => {
return a+b;
}
//void 반환값
let print = ():void => {
console.log('print');
}
매개변수의 개수에 맞게 전달해야 한다. 만약, 개수보다 적거나 많게 전달하면 에러가 발생한다.
default parmater
값으로 동작한다.optional parmeter
는 ?
를 추가한다.//매개변수 값을 정해놓을 경우
function personInfo (name: string, grade=1): string => {
return `${name} is ${grade} grade.`;
}
personInfo('John');
personInfo('John', undefined);
personInfo('John', 1);
//위 세 함수는 'John is 1 grade.' 로 같은 값을 반환한다.
//선택적 매개변수를 사용하고자 할 때는 ? 를 사용한다.
let sayHello = (firstName: string, lastName?: string): string => {
return `Hello, ${firstName} ${lastName}`;
}
sayHello('Leo'); //'Hello, Leo undefined' =>두번째 인자를 전달하지 않아도 에러 발생하지 않지만 두번째 인자는 undefined 로 인식
sayHello('Leo', 'Messi'); //'Hello, Leo Messi'
2개 이상의 타입을 허용하는 경우, 유니언 Union 이라 하고 |
파이프를 통해 타입을 구분한다.
let union: string | number;
union = 'this is union';
union = 1234;
union = false; //에러 발생 => union 은 string 혹은 number 타입만 가능
let arr: (string | number)[] = ['Apple', 1, 2, 'Banana', 'Mango
, 3];
let arr: Array<string | number> = ['Apple', 1, 2, 'Banana', 'Mango
, 3];
함수의 전달인자로 string or number 로 받는데, 유니언은 타입 추론 가능하므로 타입과 관련된 API를 쉽게 자동완성으로 얻어낼 수 있다.
하지만 주의해야할 점이 있다.
interface Person {
name: string;
age: number;
}
interface Developer {
naem: string;
skill: string;
}
function introduce(somone: Person | Developer){
someone.name; // O 공통 속성이므로 정상 동작
someone.age; // X 타입 오류
someone.skill; // X 타입 오류
}
다음과 같은 introduce 함수의 전달인자로 Person 이나 Developer 인터페이스를 사용하는데, 두 인터페이스에 공통 속성인 name 만 접근할 수 있고, age 나 skill 에는 접근할 수가 없다. 타입스크립트 관점에서는 함수를 호출하는 시점에서 Person 이 올지 Developer 가 올지 미리 알수가 없기 때문이다.
&
를 사용해 2개 이상의 타입을 조합하는 경우, 인터섹션 Intersection 이라고 한다.
새로운 타입을 생성하지 않고 기존의 타입들로 조합할 수 있다.
let value: string&number&boolean;
//value 는 string, number, boolean 타입을 모두 받을 수 있다.
interface Person {
name: string;
age: number;
}
interface Developer {
name: string;
skill: string;
}
const neo: Person & Developer = {
name: 'Neo',
age: 85,
skill: 11,
};
&
를 이용해 두 인터페이스를 합쳐 하나의 타입을 구성하는 neo 는 union으로 공통 속성만 접근할 수 있는 것과는 반대로 각각의 인터페이스의 속성 name, age, skill 에 모두 접근가능하다.