
이와 같은 유형을 데이터 타입(자료형) 이라고 하며, 이를 통해 컴파일러에 값의 형태를 알려 줄 수 있고, 컴파일러는 데이터 타입에 따라 다른 크기의 메모리 할당을 해주어, 효율적으로 메모리를 사용할 수 있다
const num: number = 123;
const str: string = "abc";
function func(n: number) {
// ...
}
func(str); // Argument of type 'string' is not assignable to parameter of type 'number'
타입 시스템은 코드에서 사용되는 유효한 값의 범위를 제한해서 런타임에서 발생할 수 있는 유효하지 않은 값에 대한 에러를 방지해준다.
number 타입으로 제한하여, string 타입의 인자를 들어오게 못하고 있다.function double(n) {
return n * 2;
}
double(2); // 4
double("z"); // NaN
function double(n: number) {
return n * 2;
}
double(2); // 4
double("z"); // 🚨 Error: Argument of type 'string' is not assignable to parameter of type 'number'.(2345)
C, JAVA, TypeScript 같은 정적 타입 언어는 개발자가 타입을 명시해줘야 하지만, 컴파일타임에 타입 에러를 발견할 수 있기 때문에 안정성을 보장할 수 있다.Python, JavaScript같은 동적 타입 언어는 개발자가 직접 타입을 정의해줄 필요가 없어 편리하지만, 프로그램에 오류가 발생할 수 있다.기계어로 변환하는 시점이 컴파일타임, 변환된 파일이 메모리에 적재되어 실행되는 시점을 런타임이라고 부른다.
타입이 결정되는 시점은 다르지만 모든 프로그래밍 언어에는 값의 타입이 존재한다.
개발자가 의도적으로 타입을 명시하거나 바꾸지 않았는데도 컴파일러 또는 엔진에 의해서 런타임에 타입이 자동으로 변경되는 것을 암묵적 타입 변환이라고 한다.
암묵적 타입 변환 여부에 따라 타입 시스템을 강타입과 약타입으로 분류 할 수 있다.
강타입 특징을 가진 언어에서는 서로 다른 타입을 갖는 값끼리 연산을 시도하면 컴파일 에러 또는 인터프리터 에러가 발생한다.
약타입 특징을 갖는 언어에서 서로 다른 타입을 갖는 값끼리 연산을 시도하면 컴파일러 또는 인터프리터가 내부적으로 판단해서 특정 값의 타입을 변환하여 연산을 수행한다.
C++, 자바, 자바스크립트는 약타입 언어, 파이썬, 루비, 타입스크립트는 강타입 언어로 분류할 수 있다.
자바스크립트는 약타입 언어이기 때문에, 타입 안정성을 생각하며 코드를 작성해야하며, 타입을 명시해서 코드를 작성한 후에는 개발자의 의도가 논리적으로 합당한지 검사하는 기준이 필요하다.
타입 검사기가 프로그램에 타입을 할당하는데 사용하는 규칙 집합을 타입 시스템이라고 하며, 타입 시스템은 어떤 타입을 사용하는지를 컴파일러에 명시적으로 알려줘야하는 시스템, 자동으로 타입을 추론하는 시스템이 존재한다.
타입스크립트는 두 가지 타입 시스템의 영향을 모두 받았다.
타입스크립트의 존재의의 자체가 자바스크립트의 컴파일타임에 런타임 에러를 사전에 잡아내기 위함이기 때문이다.
: type 구문을 붙여 데이터 타입을 명시해준다.let isDone: boolean = false;
let decimal: number = 6;
let color: string = "blue";
let list: number[] = [1, 2, 3];
let x: [string, number]; // tuple
: type 구문이 없어도 정상적으로 동작을 한다.class Animal {
String name;
int age;
}
interface Developer {
faceValue: number;
}
interface BankNote {
faceValue: number;
}
let developer: Developer = { faceValue: 52 };
let bankNote: BankNote = { faceValue: 10000 };
developer = bankNote; // OK
bankNote = developer; // OK
하지만 타입스크립트에서 타입을 구분하는 방식은 조금 다르다. 이름으로 타입을 구분하는 명목적인 타입 언어의 특징과 달리 타입스크립트는 구조로 타입을 구분하며, 이것을 구조적 타이핑이라고 한다.
type stringOrNumber = string | number;
구조적 서브타이핑이란 객체가 가지고 있는 프로퍼티를 바탕으로 타입을 구분하는 것이다.
이름이 다른 객체라도 가진 속성이 동일하다면 타입스크립트에서는 서로 호환이 가능한 동일한 타입이다.
interface Pet {
name: string
}
interface Cat {
name: string
age: number
}
let pet: Pet;
let cat: Cat = { name: "Zag", age: 2 };
// ✅ OK
pet = cat;
Cat은 Pet과 다른 타입으로 선언되었지만, Pet이 가진 name프로퍼티를 Cat도 가지고 있기 때문에 Cat 타입으로 선언한 cat을 Pet 타입으로 선언한 pet에 할당 가능하다.interface Pet {
name: string
}
let cat = { name: "Zag", age: 2 };
function greet(pet: Pet) {
console.log(`Hello, ${pet.name}`);
}
greet(cat); // ✅ OK
다음과 같이 함수의 매개변수에도 적용된다.
함수의 매개변수로 제한한 Pet 타입이 존재하며, cat 객체는 Pet 타입이 가지고 있는 name 프로퍼티를 가지고 있기 때문에 함수의 매개변수로 전달하여도 정상 작동한다.
타입스크립트의 타입의 상속에 대해서도 이러한 구조적 타이핑이 기반이 되고있다.
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
class Developer {
name: string;
age: number;
sleepTime: number;
constructor(name: string, age: number, sleepTime: number) {
this.name = name;
this.age = age;
this.sleepTime = sleepTime;
}
}
function greet(p: Person) {
console.log(`Hello, I'm ${p.name}`);
}
const developer = new Developer("zig", 20, 7);
greet(developer); // Hello, I'm zig
Developer 클래스가 Person 클래스를 상속받지 않았더라도, Person이 가지고 있는 속성을 가지고 있기 때문에 greet(developer) 이 정상 작동한다.이처럼 서로 다른 두 타입간의 호환성은 오로지 타입 내부의 구조에 의해 결정되며, 타입 A가 타입 B의 서브 타입이라면 A타입의 인스턴스는 B타입이 필요한 곳에 언제든지 위치할 수 있다.
class Cat {
String name;
public void hit() {}
}
class Arrow {
String name;
public void hit() {}
}
public class Main {
public static void main(String[] args) {
// error: incompatible types: Cat cannot be converted to Arrow
Arrow cat = new Cat();
// error: incompatible types: Arrow cannot be converted to Cat
Cat arrow = new Arrow();
}
}
자바스크립트는 어떤 타입에 부합하는 변수와 메서드를 가질 경우 해당 타입에 속하는 것으로 간주하는 덕 타이핑 방식을 채택하고 있다.
- 이처럼 구조적 타이핑 덕분에 타입스크립트는 더욱 유연한 타이핑이 가능해졌다.
덕 타이핑과 구조적 타이핑 모두 이름이 아닌 객체가 가진 속성을 기반으로 타입을 구분한다는 공통점이 있다
하지만 덕 타이핑은 런타임에 타입을 검사하고, 구조적 타이핑은 컴파일타임에 타입체크를 검사한다.
interface Cube {
width: number
height: number
depth: number
}
function addLines(c: Cube) {
let total = 0;
for (const axis of Object.keys(c)) {
// 🚨 Element implicitly has an 'any' type
// because expression of type 'string' can't be used to index type 'Cube'.
// 🚨 No index signature with a parameter of type 'string'
// was found on type 'Cube'
const length = c[axis];
total += length;
}
}
addLines 함수의 매개변수인 c는 Cube 타입으로 선언되었고, Cube 인터페이스의 모든 필드는 number 타입을 가지기 때문에 c[axis]가 당연히 number 타입이라고 예측할 수 있다.c에 들어올 객체는 Cube의 width, height, depth 외에도 어떤 속성이든 가질 수 있기 때문에 c[axis]는 string일 수도 있어서 에러가 발생한다.function add(x, y) {
return x + y;
}
// 위 코드는 아래와 같이 암시적 타입 변환이 일어난다.
function add(x: any, y: any): any
const names = ["zig", "colin"];
console.log(names[2].toUpperCase());
// 🚨 TypeError: Cannot read property 'toUpperCase' of undefined
💡
any 타입
any 타입은 말그대로 타입스크립트 내 모든 타입의 종류를 포함하는 가장 상위 타입이다.
단 타입스크립트 컴파일 옵션인 noImplicitAny 값이 true일 때는 에러가 발생한다.
이 컴파일 옵션은 타입 애너테이션이 없을 경우 any 타입으로 추론하는 것을 허락할 것인지에 대한 옵션이다. true로 설정하는 것이 정확한 타이핑을 위해 좋고, 가급적으로 any타입은 사용하지 말도록하자
function greet(name: string) {
console.log("Hello", name);
}
let developer = "Colin";
console.log(developer.toUppercase());
// Property ‘toUppercase’ does not exist on type ‘string’.
// Did you mean ‘toUpperCase’?
developer가 문자열이라는 것을 알려주지 않아도 타입스크립트는 초깃값을 통해 타입을 추론해서 메서드로 대체할 것을 제안한다.11; // 숫자 값
("hello typescript");
// 문자열 값
let foo = "bar"; // 변숫값
// 함수
function goWork(developer) {
console.log(`tired ${developer}`);
}
const developer = "zig";
// 함수
const goWork = function (developer) {
console.log(`tired ${developer}`);
};
type Person = {
name: string;
age: number;
};
interface Person {
name: string;
age: number;
}
타입스크립트가 자바스크립트의 슈퍼셋이며, 타입스크립트에서
type으로 선언한 내용은 자바스크립트 런타임에서 제거되기 때문에 값 공간과 타입 공간은 서로 충돌하지 않는다.
type Developer = { isWorking: true };
const Developer = { isTyping: true }; // OK
type Cat = { name: string; age: number };
const Cat = { slideStuffOffTheTable: true }; // OK
: 또는 단언 문 (as) 로 작성하고 값은 할당 연산자인 = 로 작성한다.interface Developer {
name: string;
isWorking: boolean;
}
const developer: Developer = { name: "Zig", isWorking: true };
function postTIL(author: Developer, date: Date, content: string): Response {
// ...
}
author, date, content → 값, Developer, Date, string → 타입function email(options: { person: Person; subject: string; body: string }) {
// ...
}
email 함수의 매개변수로 넘기는 options 객체를 다음과 같이 풀어 쓸 수 있다.function email({ person, subject, body }) {
// ...
}
function email({
person: Person, // 🚨
subject: string, // 🚨
body: string, // 🚨
}) {
// ...
}
값의 관점에서
Person과string이 해석되었기 때문이다. 개발자의 의도는 매개변수 객체의 속성인person을Person타입으로,subject,body를string타입으로 설정하는 것이었지만, 위 코드에서는Person과string이 값 공간에 있는 것으로 해석되고,person과Person은 각 함수의 매개변수 객체 내부 속성의 키-값 쌍으로 해당하는 것으로 해석된다.
올바르게 작성하려면 값과 타입을 구분해서 작성해야한다.
function email({
person,
subject,
body,
}: {
person: Person;
subject: string;
body: string;
}) {
// ...
}
타입스크립트에서는 값과 타입이 동시에 존재하는 심볼이 있으며, 이는 클래스와 enum이다.
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
const rect1 = new Rectangle(5, 4);
class Developer {
name: string;
domain: string;
constructor(name: string, domain: string) {
this.name = name;
this.domain = domain;
}
}
const me: Developer = new Developer("zig", "frontend");
me 뒤에 등장하는 : Developer에서 Developer는 타입에 해당하지만, new 키워드 뒤의 Developer는 클래스의 생성자 함수인 값으로 동작한다.enum
마찬가지로 enum 역시 런타임에 객체로 변환되는 값이다. enum은 런타임에 실제 객체로 존재하며, 함수로 표현할 수도 있다.
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right, // 3
}
// 순수 자바스크립트 코드로 컴파일한 결과
let Direction;
(function (Direction) {
Direction[(Direction.Up = 0)] = "Up";
Direction[(Direction.Down = 1)] = "Down";
Direction[(Direction.Left = 2)] = "Left";
Direction[(Direction.Right = 3)] = "Right";
})(Direction || (Direction = {}));
enum도 클래스처럼 타입 공간에서 타입을 제한하는 역할을 하지만 자바스크립트 런타임에서 실제 값으로도 사용될 수 있다.// enum이 타입으로 사용된 경우
enum WeekDays {
MON = "Mon",
TUES = "Tues",
WEDNES = "Wednes",
<THURS = "Thurs",
FRI = "Fri",
}
// ‘MON’ | ‘TUES’ | ‘WEDNES’ | ‘THURS’ | ‘FRI’
type WeekDaysKey = keyof typeof WeekDays;
function printDay(key: WeekDaysKey, message: string) {
const day = WeekDays[key];
if (day <= WeekDays.WEDNES) {
console.log(`It’s still ${day}day, ${message}`);
}
}
printDay("TUES", "wanna go home");
// enum이 값 공간에서 사용된 경우
enum MyColors {
BLUE = "#0000FF",
YELLOW = "#FFFF00",
MINT = "#2AC1BC",
}
function whatMintColor(palette: { MINT: string }) {
return palette.MINT;
}
whatMintColor(MyColors); // ✅
타입스크립트에서 어떠한 심볼이 값으로 사용된다는 것은 컴파일러를 사용해서 타입스크립트 파일을 자바스크립트 파일로 변환해도 여전히 자바스크립트 파일에 해당 정보가 남아있음을 의미한다.
반면 타입으로만 사용되는 요소는 컴파일 이후에 자바스크립트 파일에서 해당 정보가 사라진다.
| 키워드 | 값 | 타입 |
|---|---|---|
| class | Y | Y |
| const, let, var | Y | N |
| enum | Y | Y |
| function | Y | N |
| interface | N | Y |
| type | N | Y |
| namespace | Y | N |
typeof는 연산하기 전에 피연산자의 데이터 타입을 나타내는 문자열을 반환한다.Function, 호스트 객체, object 객체다.typeof 2022; // "number"
typeof "woowahan"; // "string"
typeof true; // "boolean"
typeof {}; // "object"
typeof 연산자는 값에서 쓰일 때와 타입에서 쓰일 때의 역할이 다르다.interface Person {
first: string;
last: string;
}
const person: Person = { first: "zig", last: "song" };
function email(options: { person: Person; subject: string; body: string }) {}
typeof 연산자는 자바스크립트 런타임의 typeof 연산자가 된다.// 값에서 사용될 때
const v1 = typeof person; // 값은 ‘object’
const v2 = typeof email; // 값은 ‘function’
// 타입에서 사용될 때
type T1 = typeof person; // 타입은 Person
type T2 = typeof email; // 타입은 (options: { person: Person; subject: string; body:string; }) = > void
typeof 연산자를 쓸 때 주의해야 한다.class Developer {
name: string;
sleepingTime: number;
constructor(name: string, sleepingTime: number) {
this.name = name;
this.sleepingTime = sleepingTime;
}
}
const d = typeof Developer; // 값이 ‘function’
type T = typeof Developer; // 타입이 typeof Developer
자바스크립트의 클래스는 결국 함수이기 때문에 값 공간에서
typeof Developer의 값은function이 된다.
타입 공간에서typeof Developer의 반환 값은type T에 할당된Developer는 인스턴스의 타입이 아니라new키워드를 사용할 때 볼 수 있는 생성자 함수이기 때문이다.
const zig: Developer = new Developer("zig", 7);
type ZigType = typeof zig; // 타입이 Developer
Developer 클래스로 생성한 zig 인스턴스는 Developer가 인스턴스 타입으로 생성되었기 때문에 타입 공간에서의 typeof zig 즉, type ZigType은 Developer를 반환한다.Devloper는 Developer 타입의 인스턴스를 만드는 생성자 함수이다. 따라서 typeof Developer 타입도 그 자체인 typeof Developer가 된다. typeof Developer를 풀어서 설명하면 다음과 같다.new (name: string, sleepingTime: number): Developer
instanceof
instanceof 연산자는 객체가 특정 클래스나 생성자 함수의 인스턴스인지 여부를 확인하는 데 사용된다.typeof 연산자처럼 instanceof 연산자의 필터링으로 타입이 보장된 상태에서 안전하게 값의 타입을 정제하여 사용할 수 있다.let error: unknown;
if (error instanceof Error) {
// 이 블록 내에서 error는 Error 타입으로 정제되어 사용된다.
showAlertModal(error.message); // // 안전하게 Error 클래스의 메소드를 사용할 수 있음
} else {
// error가 Error 타입이 아닌 경우의 처리
throw Error(error);
}
as 키워드를 사용해 타입을 강제할 수 있는데, 이는 개발자가 해당 값의 타입을 더 잘 파악할 수 있을 때 사용되며 강제 형 변환과 유사한 기능을 제공한다.const loaded_text: unknown; // 어딘가에서 unknown 타입 값을 전달받았다고 가정
const validateInputText = (text: string) => {
if (text.length < 10) return "최소 10글자 이상 입력해야 합니다.";
return "정상 입력된 값입니다.";
};
validateInputText(loaded_text as string); // as 키워드를 사용해서 string으로 강제하지 않으면 타입스크립트 컴파일러 단계에서 에러 발생
자바스크립트의 변수에는 어떤 타입의 값이라도 자유롭게 할당할 수 있다.
타입스크립트는 이 변수에 타입을 지정할 수 있는 타입 시스템 체계를 구축한다.
특정 타입을 지정한 변수에는 해당 타입의 값만 할당할 수 있는 식이다.
자바스크립트의 7가지 원시 값은 타입스크립트에서 원시 타입으로 존재한다.
원시 값과 원시 래퍼 객체
자바스크립트에서는 원시 값에 대응하는 원시 래퍼 객체가 있지만, 타입스크립트에서는 원시 값과 원시 래퍼 객체를 구분하여 사용한다. 타입스크립트에서는 원시 값에 대응하는 타입을 소문자로 표기하며, 파스칼 표기법을 사용하면 해당 원시 값을 래핑하는 객체 타입을 의미한다. 따라서, 타입스크립트에서는 원시 값과 원시 래퍼 객체를 구분하여 사용해야 한다.
true와 flase 값만 할당할 수 있는 boolean 타입이다.boolean 원시 값은 아니지만 형 변환을 통해 true / false로 취급되는 Tryuthy / Falsy같이 존재하는데, 이 값은 boolean 원시 값이 아니므로 타입스크립트에서도 boolean 타입에 해당하지 않는다.const isEmpty: boolean = true;
const isLoading: boolean = false;
// errorAction.type과 ERROR_TEXT가 같은지 비교한 결괏값을 boolean 타입으로 반환하는 함수
function isTextError(errorCode: ErrorCodeType): boolean {
const errorAction = getErrorAction(errorCode);
if (errorAction) {
return errorAction.type === ERROR_TEXT;
}
return false;
}
let value: string;
console.log(value); // undefined (값이 아직 할당되지 않음)
type Person = {
name: string;
job?: string;
};
undefined 값만 할당할 수 있으며, 초기화되어 있지 않거나 존재하지 않음을 나타낸다.Person타입의 job 속성은 옵셔널로 지정되어 있는데 이런 경우에도 undefined를 할당할 수 있다.let value: null | undefined;
console.log(value); // undefined (값이 아직 할당되지 않음)
value = null;
console.log(value); // null
null 만 할당할 수 있으며 보통 명시적, 의도적으로 값이 아직 비어있을 수 있음을 보여준다.null과 undefined가 비슷해보여도 엄연히 따로 존재하는 원시 값이기 때문에 서로의 타입에 할당할 수 없다.type Person1 = {
name: string;
job?: string;
};
type Person2 = {
name: string;
job: string | null;
};
Person1 은 job이라는 속성이 있을 수도 또는 없을 수도 있음을 나타낸다.Person2는 job이라는 속성을 가지고 있지만 값이 비어있을 수 있음 (무직인 상태)const maxLength: number = 10;
const maxWidth: number = 120.3;
const maximum: number = +Infinity;
const notANumber: number = NaN;
Number.MAX_SAFE_INTEGER(2^53 -1)보다 큰 수를 처리할 수 있다.number 타입과 bigint 타입은 엄연히 서로 다른 타입이기 때문에 상호작용을 불가능하다.const bigNumber1: bigint = BigInt(999999999999);
const bigNumber2: bigint = 999999999999n;
const receiverName: string = “KG”;
const receiverPhoneNumber: string = “010-0000-0000”;
const letterContent: string = `안녕, 내 이름은 ${senderName}이야.`;
Symbol() 함수를 사용하면 어떤 값과도 중복되지 않는 유일한 값을 생성할 수 있다.const 선언에서만 사용할 수 있는 unique symbol 타입이라는 symbol의 하위 타입도 있다.const MOVIE_TITLE = Symbol("title");
const MUSIC_TITLE = Symbol("title");
console.log(MOVIE_TITLE === MUSIC_TITLE); // false
let SYMBOL: unique symbol = Symbol(); // A variable whose type is a 'unique symbol'
// type must be 'const'
any 타입과 유사하게 객체에 대항하는 모든 타입 값을 유동적으로 할당할 수 있어 정적 타이핑의 의미가 크게 퇴색되기 때문에 가급적 사용하지 말도록 권장되는 타입이다.any와는 다르게 원시 타입에 해당하는 값은 object 타입에 속하지 않는다.function isObject(value: object) {
return (
Object.prototype.toString.call(value).replace(/\[|\]|\s|object/g, "") ===
"Object"
);
}
// 객체, 배열, 정규 표현식, 함수, 클래스 등 모두 object 타입과 호환된다
isObject({});
isObject({ name: "KG" });
isObject([0, 1, 2]);
isObject(new RegExp("object"));
isObject(() => {
console.log("hello wolrd");
});
isObject(class Class {});
// 그러나 원시 타입은 호환되지 않는다
isObject(20); // false
isObject("KG"); // false
{} 안에 지정할 수 있다// 정상
const noticePopup: { title: string; description: string } = {
title: "IE 지원 종료 안내",
description: "2022.07.15일부로 배민상회 IE 브라우저 지원을 종료합니다.",
};
// SyntaxError
const noticePopup: { title: string; description: string } = {
title: "IE 지원 종료 안내",
description: "2022.07.15일부로 배민상회 IE 브라우저 지원을 종료합니다.",
startAt: "2022.07.15 10:00:00", // startAt은 지정한 타입에 존재하지 않으므로 오류
};
{}를 사용할 수 있지만, {} 타입으로 지정된 객체에는 어떤 값도 속성으로 할당할 수 없다let noticePopup: {} = {};
noticePopup.title = "IE 지원 종료 안내"; // (X) title 속성을 지정할 수 없음
{}타입으로 지정된 객체는 완전히 비어있는 순수한 객체를 의미하는 것이 아니다.그러나 자바스크립트의 프로토타입 체이닝 때문에 아래와 같이 기본
Object객체의 메서드는 사용할 수 있다.
console.log(noticePopup.toString()); // [object Object]
array라는 별도 타입으로 다루며, 하나의 타입 값만 가질 수 있다는 점에서 자바스크립트 배열보다 조금 더 엄격하다. 하지만 원소 개수는 타입에 영향을 주지 않는다.Array 키워드로 선언하거나 []를 사용해서 선언하는 방법이 있다.const getCartList = async (cartId: number[]) => {
const res = await CartApi.GET_CART_LIST(cartId);
return res.getData();
};
getCartList([]); // (O) 빈 배열도 가능하다
getCartList([1001]); // (O)
getCartList([1001, 1002, 1003]); // (O) number 타입 원소 몇 개가 들어와도 상관없다
getCartList([1001, "1002"]); // (X) ‘1002’는 string 타입이므로 불가하다
const targetCodes: ["CATEGORY", "EXHIBITION"] = ["CATEGORY", "EXHIBITION"]; // (O)
const targetCodes: ["CATEGORY", "EXHIBITION"] = [
"CATEGORY",
"EXHIBITION",
"SALE",
]; // (X) SALE은 지정할 수 없음
type과 interface가 있다.type NoticePopupType = {
title: string;
description: string;
};
interface INoticePopup {
title: string;
description: string;
}
const noticePopup1: NoticePopupType = {
/* ... */
};
const noticePopup2: INoticePopup = {
/* ... */
};
💡
type과 interface 사용 상황:
interface를, 작은 범위 내에서 한정적인 용도로는 type을 사용합니다.interface를 선호합니다.type과 interface를 둘 다 사용하며, computed value가 필요할 때는 type을 사용합니다interface의 이름이 노출되는 상황에서는 interface를 사용하며, 리턴 타입이 확정적일 때는 type을 선호합니다.type이나 interface만을 써야 하는 상황:
interface가 더 적합합니다.type을 활용하며, 복잡한 구조의 경우에는 interface를 선호합니다.props 형태에서 Record를 사용하는 상황에서 interface로 변환할 때 오류가 발생하는 경우가 있어, 그 상황에 따라 선택합니다.computed value가 필요할 때는 type을 주로 사용합니다.typeof 연산자로 함수 타입을 출력하면 function이라는 별도의 타입으로 분류한다는 것을 알 수 있다.function add(a, b) {
return a + b;
}
console.log(typeof add); // ‘function’
typeof 연산자로 확인한 function 이라는 키워드 자체를 타입으로 사용하지 않는다.function add(a: number, b: number): number {
return a + b;
}
💡
그런데, 함수 자체의 타입은 어떻게 지정할 수 있을까? 호출 시그니처를 정의하는 방식을 사용하면 된다.
호출 시그니처(Call Signature)
타입스크립트에서 함수 타입을 정의할 때 사용하는 문법이다. 함수 타입은 해당 함수가 받는 매개변수와 반환하는 값의 타입으로 결정된다. 호출 시그니처는 이러한 함수의 매개변수와 반환 값의 타입을 명시하는 역할을 한다.
type add = (a: number, b: number) => number;