TypeScript와 JavaScript의 관계는 다소 독특하다. TypeScript는 JavaScript의 모든 특징을 제공하면서, 그 위에 TypeScript의 타입 시스템이라는 층을 추가한다. 예를 들어, JavaScript는 이미 string, number, object, undefined 같은 원시 타입을 제공하고 있지만, 전체 코드베이스에 일관되게 할당되었는지 미리 확인해주지 않는다. 하지만 TypeScript는 확인해준다.
이는 기존에 동작하고 있는 JavaScript 코드는 또한 TypeScript 코드라는 것을 의미한다. TypeScript의 주요 이점은 코드에서 발생하는 예상치 못한 행동을 강조할 수 있고 이로 인해, 버그를 줄일 수 있다는 것이다.
let helloWorld = "Hello world";
// let helloWorld: string
JavaScript가 동작하는 방식을 이해함으로써, TypeScript는 JavaScript 코드를 받아들이면서 타입 시스템을 구축할 수 있다. 이는 코드에서 타입을 명시하기 위해 추가로 문자를 사용할 필요 없는 타입 시스템을 제공한다. 이것이 위의 예제에서 TypeScript가 helloWorld
가 string
임을 알게 되는 방식이다.name: string
과 id: number
을 포함하는 추론 타입을 가진 객체를 생성하는 예제이다.const user = {
name: "daeman",
id: 14,
};
이 객체의 형태를 명시적으로 나타내기 위해서는 interface로 선언한다,interface User {
name: string;
id: number;
}
이제 변수 선언 뒤에 : TypeName
의 구문을 사용해서 JavaScript 객체가 새로운 interface
의 형태를 따르고 있음을 선언할 수 있다.interface User {
name: string;
id: number;
}
// --- cut ---
const user: User = {
name: "daeman",
id: 14,
};
해당 인터페이스에 맞지 않는 객체를 생성하면 TypeScript는 경고를 준다.// @errors: 2322
interface User {
name: string;
id: number;
}
// --- cut ---
const user: User = {
username: "daeman", // X
id: 14,
};
JavaScript는 클래스와 객체 지향 프로그래밍을 지원하기 때문에, TypeScript 또한 동일하다. - 인터페이스는 클래스로도 선언할 수 있다.interface User {
name: string;
id: number;
}
class UserAccount {
name: string;
id: number;
constructor(name: string, id: number) {
this.name = name;
this.id = id;
}
}
const user: User = new UserAccount("daeman", 14);
인터페이스는 함수에서 매개변수와 리턴값을 명시하는데 사용되기도 한다.// @noErrors
interface User {
name: string;
id: number;
}
// --- cut ---
function getAdminUser(): User {
// ...
}
function deleteUser(user: User) {
// ...
}
boolean
, bigint
, null
, number
, string
, symbol
, object
, undefined
는 인터페이스에서 사용할 수 있다. TypeScript에서는 여기에 몇 가지를 추가했다. any
(무엇이든 허용), unknown
(이 타입을 사용하는 사람이 어떤 타입으로 정의했는지 확인), never
(이 타입은 발생할 수 없다), void
(undefined를 리턴하거나 리턴할 값이 없는 함수) 타입 구축을 위한 두 개의 구문이 있다 : Interfaces와 Types. interface
를 우선적으로 사용하고 types
는 특정한 기능이 필요할 때만 사용한다.type MyBool = true | false;
Note : MyBool은 boolean 타입이며, 구조적 타입 시스템의 프로퍼티이다. 유니온 타입이 많이 사용되는 사례는 값이 될 수 있는 string이나 number의 리터럴 집합을 묘사할 때이다.type WindowStates = "open" | "closed" | "minimized";
type LockStates = "locked" | "unlocked";
type PositiveOddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
유니온은 다른 타입들을 다루는 방법도 제공한다. 예를 들어, array나 string 타입을 갖는 함수를 생성할 수 있다function getLength(obj: string | string[]) {
return obj.length;
}
Type | Predicate |
---|---|
string | typeof s === “string” |
number | typeof n === “number |
boolean | typeof b === “boolean” |
undefined | typeof undefined === “undefined” |
function | typeof f === “function” |
array | Array.isArray(a) |
function wrapInArray (obj: string | string[]) {
if (typeof obj === "string") {
return [obj]; // (parameter) obj: string
}
return obj; // (parameter) obj: string[]
}
type StringArray = Array<string>;
type NumberArray = Array<number>;
type ObjectWtihNameArray = Array<{ name: string }>;
제네릭을 사용하면 고유의 타입을 선언할 수 있다.interface Backpack<Type> {
add: (obj: Type) => void;
get: () => Type;
}
// 이 줄은 TypeScript에 `backpack`이라는 상수가 있다고 알리는 쉬운 방법이며,
// 어디서 왔는지 걱정하지 않아도 된다.
declare const backpack: BackPack<string>;
// object는 string이다, 왜냐하면 위에서 BackPack을 변수 부분에서 선언했기 때문이다.
const object = backpack.get();
// backpack 변수는 string이기 때문에, add 함수에 숫자를 넘겨줄 수 없다.
backpack.add(23); // error
// number 타입의 인수는 string 타입의 파라미터에 할당 할 수 없다.
interface Point {
x: number;
y: number;
}
function logPoint(p: Point) {
console.log(`${p.x}, ${p.y}`); // 12, 26
}
const point = { x: 12, y: 26 };
logPoint(point);
point
변수는 Point
타입으로 선언되지 않았다. 하지만, TypeScript는 타입 체크를 할 때, point
의 형태를 Point
의 형태와 비교했다. 둘 다 똑같은 형태를 가졌고, 그래서 코드가 통과했다. 이러한 형태 매칭은 일치하는 객체 필드의 하위 집합만 필요하다.const point3 = { x: 12, y: 26, z: 89 };
logPoint(point3); // 12, 26
const rect = { x: 33, y: 3, width: 30, height: 80 };
logPoint(rect); // 33, 3
const color = { hex: "#187ABF" }; // error
// '{ hex: "#187ABF" }' 인자는 'Point' 타입의 파라미터에 할당할 수 없다.
// '{ hex: "#187ABF" }' 타입은 'Point': x, y 타입의 속성이 없다.
클래스로 하는 방법도 위의 방법과 동일하다.class VirtualPoint {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
const newVPoint = new VirtualPoint(13, 56);
logPoint(newVPoint); // 13, 56
만약 객체나 클래스에 필요한 모든 속성이 있는 경우, TypeScript는 구현 세부 사항에 관계 없이 일치한다고 말할 것이다.출처
(en) https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html
(kor) https://typescript-kr.github.io/pages/tutorials/ts-for-js-programmers.html