$ mkdir ts-practice # ts-practice 라는 디렉터리 생성
$ cd ts-practice # 해당 디렉터리로 이동
$ yarn init -y # 또는 npm init -y
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true
}
}
$ yarn global add typescript
$ tsc --init // tsconfig.json 자동생성
error
zsh: command not found: tsc
해결
brew install typescript
src/practice.ts
const message: string = 'hello world';
console.log(message);
타입스크립트는 이렇게 *.ts 확장자를 사용하고, message 값이 선언된 코드에 : string 부분이 해당 상수 값이 문자열 이라는 것을 명시해준다.
해당 값을 string이 아닌 타입을 설정한다면 에디터 상에서 오류가 나타나게 된다.
let count = 0;
count += 1;
count = '문자열 넣으면 에러';
const message: string = 'hello';
const done: boolean = true;
const numbers: number[] = [1,2,3] //숫자 배열
const messages: string[] = ['hello', 'world'] // 문자열 배열
message.push(1); // 숫자 넣으면 에러
let mightBeUndefined: string | undefined = undefined;
// string 또는 undefined
let nullableNumber: number | null = null;
// number 또는 null
let color: 'red' | 'orange' | 'yellow' = 'red'; // 셋 중 하나
color = 'yellow';
color = 'green'; // error!
TypeScript 를 사용하면 이렇게 특정 변수 또는 상수의 타입을 지정 할 수 있고 우리가 사전에 지정한 타입이 아닌 값이 설정 될 때 바로 에러를 발생시킨다.
이렇게 에러가 나타났을땐 컴파일이 되지 않는다. 한번 tsc 명령어를 입력해서 컴파일을 하려고 하면 다음과 같이 실패한다.
$ tsc
src/practice.ts:3:1 - error TS2322: Type '"문자열 넣으면 에러"' is not assignable to type 'number'.
3 count = "문자열 넣으면 에러";
~~~~~
src/practice.ts:12:9 - error TS2339: Property 'push' does not exist on type 'string'.
12 message.push(1); // 숫자 넣으면 에러
~~~~
src/practice.ts:21:1 - error TS2322: Type '"green"' is not assignable to type '"red" | "orange" | "yellow"'.
21 color = "green"; // error!
~~~~~
Found 3 errors.
function sum(x: number, y: number): number {
return x + y;
}
sum()
타입스크립트를 사용하면 다음과 같이 코드를 작성하는 과정에서 함수의 파라미터로 어떤 타입을 넣어야 하는지 바로 알 수 있다.
function sumArray(numbers: number[]): number {
return numbers.reduce((acc, current) => acc + current, 0);
}
const total = sumArray([1, 2, 3, 4, 5]);
배열의 내장함수를 사용할 때도 타입 유추가 매우 잘 이루어진다.
만약 아무것도 return하지 않는 함수의 경우에는 void 타입을 지정해준다.
function returnNothing(): void {
console.log("I am just saying hello world");
}
interface
interface는 클래스 또는 객체를 위한 타입을 지정 할 때 사용되는 문법
클래스와 관련된 타입의 경우엔 interface 를 사용하는게 좋고, 일반 객체의 타입의 경우엔 그냥 type을 사용해도 무방하다.
interface Person {
name: string;
age?: number; // ? = 설정을 해도 되고 안해도 되는 값.
}
interface Developer extends Person {
skills: string[];
}
const person: Person = {
name: "김사람",
age: 20,
};
const expert: Developer = {
name: "김개발",
skills: ["javascript", "react"],
};
const people: Person[] = [person, expert];
제너릭(Generics)은 타입스크립트에서 함수, 클래스, interface, type alias 를 사용하게 될 때 여러 종류의 타입에 대하여 호환을 맞춰야 하는 상황에서 사용하는 문법이다.
함수에서 Generics 사용하기
예를 들어서 우리가 객체 A 와 객체 B 를 합쳐주는 merge 라는 함수를 만든다고 가정해봅시다. 그런 상황에서는 A 와 B 가 어떤 타입이 올 지 모르기 떄문에 이런 상황에서는 any 라는 타입을 쓸 수도 있습니다.
function merge(a: any, b: any): any {
return {
...a,
...b
};
}
const merged = merge({ foo: 1 }, { bar: 1 });
이렇게 하면 타입 유추가 모두 깨진거나 다름이 없다. 결과가 any 라는 것은 즉 merged 안에 무엇이 있는지 알 수 없다는 것이다.
이런 상황에 Generics 를 사용하면 된다.
function merge<A, B>(a: A, b: B): A & B {
return {
...a,
...b,
};
}
const merged = merge({ foo: 1 }, { bar: 1 });