# 터미널에서 입력할 명령어들
$ mkdir ts-practice # ts-practice 라는 디렉터리 생성
$ cd ts-practice # 해당 디렉터리로 이동
$ yarn init -y # 또는 npm init -y
→ ts-practice
디렉터리에 package.json
파일 형성
위치 및 파일명
위치: 프로젝트 디렉터리 내부
파일명: tsconfig.json
파일의 역할
타입스크립트가 컴파일 될 때 필요한 옵션 지정
코드
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist" // 추가된 속성
}
}
생성 방법
직접 입력
명령어 사용 (일반적)
typescript
를 글로벌로 설치
$ yarn global add typescript
프로젝트 디렉터리 내부에서 tsc --init
입력 → tsconfig.json
파일 자동생성
만약, 명령어 작동 x
npm install -g typescript
하고 다시 명령어 실행
설정의 의미
(tsc --init
를 통해) 기본적으로 설정된 것들의 의미
target
컴파일된 코드가 어떤 환경에서 실행될 지 정의
target 설정 | es5 | es6 |
---|---|---|
화살표 함수 사용 시 | 일반 function 키워드를 사용하는 함수로 변환 | 유지 |
module
컴파일된 코드가 어떤 모듈 시스템을 사용할지 정의
module 설정 | common | es2015 |
---|---|---|
export default Sample 을 하게 됐을 때, 컴파일된 코드에서 | exports.default = helloWorld | |
로 변환 | 유지 |
strict
모든 타입 체킹 옵션을 활성화
esModuleInterop
commonjs 모듈 형태로 이루어진 파일을 es2015 모듈 형태로 불러올 수 있게 함.
outDir
(속성 추가)
컴파일된 파일들이 저장되는 경로를 지정
*.ts
란?타입스크립트가 사용하는 확장자
src/practice.ts
) const message: string = 'hello world';
console.log(message);
tsc
입력
터미널에서 (해당 프로젝트의 디렉터리에 위치)
파일 생성됨 (dist/practice.js
)
→ ts
파일에서 명시한 값의 타입은 컴파일이 되는 과정에서 모두 사라짐.
"use strict";
var message = 'hello world';
console.log(message);
// src/practice.ts
let count = 0; // 숫자
count += 1;
count = '갑자기 분위기 문자열'; // 이러면 에러가 납니다!
const message: string = 'hello world'; // 문자열
const done: boolean = true; // 불리언 값
const numbers: number[] = [1, 2, 3]; // 숫자 배열
const messages: string[] = ['hello', 'world']; // 문자열 배열
messages.push(1); // 숫자 넣으려고 하면.. 안된다!
let mightBeUndefined: string | undefined = undefined; // string 일수도 있고 undefined 일수도 있음
let nullableNumber: number | null = null; // number 일수도 있고 null 일수도 있음
let color: 'red' | 'orange' | 'yellow' = 'red'; // red, orange, yellow 중 하나임
color = 'yellow';
color = 'green'; // 에러 발생!
TS 사용 시
→ 특정 변수 or 상수 타입 지정 가능
→ 지정한 타입이 아닌 값 설정 시, 에러 발생
에러 발생 시
→ 컴파일 불가
→ 컴파일 시도(tsc
입력) 하면 실패
// src/practice.ts
function sum(x: number, y: number): number {
return x + y;
}
sum(1, 2);
TS 사용 특징
코드 작성 과정 중, 함수의 파라미터로 어떤 타입을 넣어야 하는지 파악 가능
함수 결과물의 타입
: number
(첫 줄 가장 우측)
에러 예시
결과물이 number 라고 명시 후, null 반환 → 오류
// src/practice.ts
// 숫자 배열의 총합
function sumArray(numbers: number[]): number {
return numbers.reduce((acc, current) => acc + current, 0);
}
const total = sumArray([1, 2, 3, 4, 5]);
TS 사용 특징
배열의 내장 함수 사용 시 → 타입 유추가 잘 이루어짐
함수에서 아무것도 반환하지 않아야 한다면
→ 반환 타입: void
로 설정
function returnNothing(): void {
console.log('I am just saying hello world');
}
interface란?
클래스 또는 객체를 위한 타입을 지정 할 때 사용되는 문법
// src/practice.ts
// interface 선언 (Shape)
interface Shape {
getArea(): number; // Shape interface에는 getArea 함수 필수(반환값은 number)
}
class Circle implements Shape {
// 'implements' 사용 -> 해당 클래스가 Shape interface의 조건을 충족하겠다는 것을 명시
radius: number; // 멤버 변수 radius 값을 설정
constructor(radius: number) {
this.radius = radius;
}
// 너비를 가져오는 함수
getArea() {
return this.radius * this.radius * Math.PI;
}
}
class Rectangle implements Shape {
width: number;
height: number;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
const Shapes: Shape[] = [new Circle(5), new Rectangle(10, 5)];
Shapes.forEach((shape) => {
console.log(shape.getArea());
});
tsc
입력
컴파일된 스크립트 실행 (node dist/practice
입력)
멤버 변수 선언 후, constructor에서 해당 값들 하나하나 설정
width: number;
height: number;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
}
직접 하나하나 설정하는 작업 생략 가능
constructor
의 파라미터 쪽에 public
또는 private
accessor 사용
코드
// interface 선언 (Shape)
interface Shape {
getArea(): number; // Shape interface에는 getArea 함수 필수(반환값은 number)
}
class Circle implements Shape {
// 'implements' 사용 -> 해당 클래스가 Shape interface의 조건을 충족하겠다는 것을 명시
constructor(public radius: number) {
this.radius = radius;
}
// 너비를 가져오는 함수
getArea() {
return this.radius * this.radius * Math.PI;
}
}
class Rectangle implements Shape {
constructor(private width: number, private height: number) {
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
const circle = new Circle(5);
const rectangle = new Rectangle(10, 5);
console.log(circle.radius); // 클래스 외부에서 조회 가능
// console.log(rectangle.width); // 클래스 외부에서 조회 불가
const Shapes: Shape[] = [new Circle(5), new Rectangle(10, 5)];
Shapes.forEach((shape) => {
console.log(shape.getArea());
});
설명
조회 가능 | |
---|---|
public | |
으로 선언된 값 | 클래스 외부 |
private | |
으로 선언된 값 | 클래스 내부에서만 |
실행
tsc
입력)node dist/practice
입력) C:\Users\admin\Documents\tmp_codingStudy\ts-practice>node
dist/practice
5
78.53981633974483
50
// src/practice.ts
interface Person {
name: string;
age?: number; // ?은 설정에 대한 옵션을 의미함. (해도 되고 안해도 되고)
}
interface Developer {
name: string;
age?: number;
skills: string[];
}
const person: Person = {
name: "김사람",
age: 20,
};
const expert: Developer = {
name: "김개발",
skills: ["javascript", "react"],
};
extends
상속 받기
유사한 형태일 때
interface 선언 시, 다른 interface 를 extends
키워드를 사용해서 상속 받기 가능
코드
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];
type
이란?
특정 타입에 별칭을 붙이는 용도로 사용
type
기능
예시 코드
type Person = {
name: string;
age?: number; // ?은 설정에 대한 옵션을 의미함. (해도 되고 안해도 되고)
};
// &은 Intersection 으로서 두 개 이상의 타입들을 합침.
type Developer = Person & {
skills: string[];
};
const person: Person = {
name: "김사람",
};
const expert: Developer = {
name: "김개발",
skills: ["javascript", "react"],
};
type People = Person[]; // Person[]은 앞으로 People이라는 타입으로 사용 가능
const people: People = [person, expert];
type Color = "red" | "orange" | "yellow";
const color: Color = "red";
const colors: Color[] = ["red", "orange"];
interface | type | |
---|---|---|
사용하는 것이 좋은 경우 | 클래스 관련 타입 | 일반 객체 타입 |
객체를 위한 타입 정의 시 → 무엇이든 써도 상관 x,
일관성 있게 사용
제너릭(Generics)
이란?
타입스크립트에서 함수, 클래스, interface, type alias 를 사용하게 될 때 여러 종류의 타입에 대하여 호환을 맞춰야 하는 상황에서 사용하는 문법
가정
객체 A 와 객체 B 를 합쳐주는 merge
라는 함수 제작
A, B 가 어떤 타입이 올 지 모름
기존 코드
any
타입을 쓸 수도 있음any
라는 것 == merge
안에 무엇이 있는지 알 수 없음Generics
사용 function merge(a: any, b: any): any {
return {
...a,
...b,
};
}
const merged = merge({ foo: 1 }, { bar: 1 });
function merge<A, B>(a: A, b: B): A & B {
return {
...a,
...b,
};
}
const merged = merge({ foo: 1 }, { bar: 1 });
function wrap<T>(param: T) {
return {
param
}
}
const wrapped = wrap(10);
interface Items<T> {
list: T[];
}
const items: Items<string> = {
list: ["a", "b", "c"],
};
interface 에서 Generics를 사용한것과 매우 유사
type Items<T> = {
list: T[];
};
const items: Items<string> = {
list: ['a', 'b', 'c']
};
예시 코드
Queue(데이터를 등록 할 수 있는 자료형)라는 클래스 제작
먼저 등록(enqueue)한 항목을 먼저 뽑아올 수(dequeue) 있는 성질을 가짐
class Queue<T> {
list: T[] = [];
get length() {
return this.list.length;
}
enqueue(item: T) {
this.list.push(item);
}
dequeue() {
return this.list.shift();
}
}
const queue = new Queue<number>();
queue.enqueue(0);
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
queue.enqueue(4);
console.log(queue.dequeue());
console.log(queue.dequeue());
console.log(queue.dequeue());
console.log(queue.dequeue());
console.log(queue.dequeue());
# 코드 컴파일 & 실행
$ tsc
$ node dist/practice
0
1
2
3
4
참고