TypeScript가 해결하는 문제
TypeScript는 JavaScript에 정적 타입 시스템(컴파일 타임에 타입 분석)을 추가한 언어입니다. 정적 타입 시스템은 런타임 타입 검사와 구분되며, TypeScript 코드는 최종적으로 JavaScript로 컴파일됩니다. TypeScript가 제공하는 가치는 주로 개발 시점(컴파일 시)에서 나타납니다.
- 향상된 편집기 자동 완성 (개발 생산성)
- 코드 가독성 향상 (팀 협업)
- 컴파일 시 타입 검사 (프로젝트 안정성)
변수 선언
let isDone: boolean = false;
let num: number = 1;
let str: string = 'vue3js.cn';
let arr: number[] = [1, 2, 3];
let arr2: Array<number> = [1, 2, 3]; // 제네릭 배열
let obj: object = {};
let u: undefined = undefined;
let n: null = null;
열거형 (Enum)
enum LogLevel {
info = 'info',
warn = 'warn',
error = 'error',
}
튜플 (Tuple)
// 튜플 타입 선언
let x: [string, number];
// 초기화
x = ['hello', 10]; // 정상
// 잘못된 초기화
x = [10, 'hello']; // 오류
Any
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // 정상
Void
// 반환 값이 없는 함수에 사용
function warnUser(): void {
console.log("This is my warning message");
}
인터페이스 (Interface)
타입 계약을 정의합니다. 객체는 인터페이스와 정확히 일치해야 합니다.
interface Point {
x: number;
y: number;
z?: number; // 선택적 속성
readonly l: number; // 읽기 전용
}
const point: Point = { x: 10, y: 20, z: 30, l: 40 };
const point2: Point = { x: '10', y: 20, z: 30, l: 40 }; // 오류
const point3: Point = { x: 10, y: 20, z: 30 }; // 오류
const point4: Point = { x: 10, y: 20, z: 30, l: 40, m: 50 }; // 오류
함수 매개변수와 반환 타입에도 사용됩니다.
interface Point {
x: number;
y: number;
}
function sum({ x, y}: Point): number {
return x + y;
}
sum({x:1, y:2}); // 3
클래스는 여러 인터페이스를 구현할 수 있습니다.
interface A {
name: string;
}
interface B {
sum: number;
}
class C implements A, B {
name = '32';
sum: number;
constructor() {
this.sum = 908;
}
}
제네릭 (Generic)
제네릭은 함수의 재사용성을 높이기 위해 사용됩니다. 입력 타입과 출력 타입이 동일하도록 보장합니다.
function identity<T>(arg: T): T {
return arg;
}
// 타입 추론 활용
let output = identity("myString"); // output의 타입은 string
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // length 속성이 있음을 보장
return arg;
}
// length 속성이 있는 객체만 전달 가능
loggingIdentity({length: 10, value: 3}); // 정상
유니온 타입 (Union Types)
값이 여러 타입 중 하나일 수 있음을 나타냅니다.
type arg = string | number | boolean;
const foo = (arg: arg): any => {
console.log(arg);
}
foo(1);
foo('2');
foo(true);
unknown vs any
- unknown: 모든 값을 할당할 수 있지만, 타입 검사나 타입 단언을 거치기 전까지는 해당 값에 대해 어떤 작업도 수행할 수 없습니다.
- any: 모든 값을 할당할 수 있고, 어떤 작업도 허용됩니다.
클래스 (Class)
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
let greeter = new Greeter("world");
상속
class Animal {
name: string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}
class Horse extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 45) {
console.log("Galloping...");
super.move(distanceInMeters);
}
}
let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");
sam.move(); // Slithering... Sammy the Python moved 5m.
tom.move(34); // Galloping... Tommy the Palomino moved 34m.
public
기본 접근 제어자로, 클래스 내부, 외부, 파생 클래스에서 접근 가능합니다.
const Circle = class {
public name: number = 90;
age: number;
type: string;
constructor() {
this.age = 897;
this.type = '';
}
}
protected
클래스 내부와 파생 클래스에서 접근 가능하며, 외부에서는 접근 불가능합니다.
private
클래스 내부에서만 접근 가능하며, 외부나 파생 클래스에서는 접근 불가능합니다.
class Circle {
private x: number = 90;
#y: number = 90; // private 필드 문법
test() {
this.x;
}
}
class Derived extends Circle {
out() {
this.x; // 오류
}
}
정적 멤버
static 키워드를 사용하며, 클래스 이름을 통해서만 접근할 수 있습니다.
함수
선택적 매개변수는 ?를 사용합니다.
function buildName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
나머지 매개변수는 ...를 사용합니다.
function buildName(firstName: string, ...restOfName: string[]) {
return firstName + " " + restOfName.join(" ");
}
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");