Object

2개의 게시글

TypeScript

[TypeScript] 인터페이스(Interface)

November 27, 2025

타입스크립트에는 객체의 타입을 정의하는 방법이 크게 두 가지가 있다. 하나는 앞서 배운 타입 별칭(Type Alias) 이고, 다른 하나는 이번에 다룰 인터페이스(Interface) 이다. 인터페이스는 타입에 이름을 지어주는 또 다른 문법으로, 특히 객체의 구조를 정의하는 데 특화되어 있다. 1. 기본 문법 인터페이스는 interface 키워드를 사용하여 정의한다. 타입 별칭과 문법만 조금 다를 뿐, 기본적인 기능은 거의 같다. TypeScript // 인터페이스 정의 interface Person { name: string; age: number; } // 변수에 타입 주석으로 사용 const person: Person = { name: "조태민", age: 25, }; --- 2. 프로퍼티 설정 객체 리터럴 타입에서 배웠던 선택적 프로퍼티나 읽기 전용 프로퍼티도 동일하게 사용할 수 있다. 2-1. 선택적 프로퍼티 (Optional Property) 프로퍼티 이름 뒤에 ?를 붙여서, 해당 속성이 없어도 에러가 나지 않게 설정할 수 있다. TypeScript interface Person { name: string; age?: number; // 있어도 되고 없어도 됨 } const person: Person = { name: "조태민", // age는 생략 가능 }; 2-2. 읽기 전용 프로퍼티 (Readonly Property) 프로퍼티 이름 앞에 readonly를 붙여서, 초기화 이후 값을 수정할 수 없게 만든다. TypeScript interface Person { readonly name: string; // 읽기 전용 age?: number; } const person: Person = { name: "조태민", age: 25, }; // person.name = "홍길동"; // ❌ 에러 발생 (수정 불가) --- 3. 메서드 타입 정의와 오버로딩 인터페이스 내부에서 메서드의 타입을 정의하는 방법은 두 가지가 있다. 어떤 방식을 쓰느냐에 따라 오버로딩 가능 여부가 달라지므로 주의해야 한다. 3-1. 함수 타입 표현식 (화살표 함수 형태) 가장 일반적인 형태지만, 메서드 오버로딩을 구현할 수 없다는 단점이 있다. TypeScript interface Person { sayHi: () => void; // sayHi: (a: number) => void; // ❌ 오버로딩 불가능 (에러 발생) } 3-2. 호출 시그니처 (Call Signature) 메서드 이름 뒤에 괄호를 여는 방식이다. 이 방식을 사용하면 메서드 오버로딩을 구현할 수 있다. TypeScript interface Person { sayHi(): void; sayHi(a: number): void; // ✅ 오버로딩 가능 sayHi(a: number, b: number): void; // ✅ 오버로딩 가능 } --- 4. 하이브리드 타입 (Hybrid Type) 자바스크립트에서는 함수도 객체이므로, 함수이면서 동시에 객체(프로퍼티를 가짐) 인 형태를 만들 수 있다. 인터페이스로도 이를 정의할 수 있다. TypeScript interface Func2 { (a: number): string; // 호출 시그니처 (함수로서의 역할) b: boolean; // 프로퍼티 (객체로서의 역할) } const func: Func2 = (a) => "hello"; func.b = true; --- 5. 주의할 점 (타입 별칭과의 차이) 인터페이스는 타입 별칭(type)과 거의 비슷하게 동작하지만, Union(|)이나 Intersection(&) 타입을 직접 정의할 수는 없다. TypeScript // 타입 별칭은 가능 type Type1 = number | string; // 인터페이스는 불가능 (문법 오류) // interface Person { ... } | number // ❌ 만약 인터페이스와 유니온/인터섹션을 함께 사용하고 싶다면, 타입 별칭을 이용해 합치거나 타입 주석에서 직접 사용해야 한다. TypeScript interface Person { name: string; age: number; } // 타입 별칭을 이용해 결합 type Type1 = number | string | Person; // 변수 선언 시 결합 const person: Person & string = { name: "조태민", age: 25, // ... string 메서드 등 }; --- 요약 1. 인터페이스: 객체의 구조를 정의하는 문법이다 (interface Name { ... }). 2. 프로퍼티: 선택적(?), 읽기 전용(readonly) 설정이 가능하다. 3. 메서드: - func: () => void (함수 타입 표현식) -> 오버로딩 불가 ❌ - func(): void (호출 시그니처) -> 오버로딩 가능 ✅ 4. 한계: 인터페이스 자체적으로 Union이나 Intersection을 생성할 수 없다 (타입 별칭과 조합하여 해결).

TypeScriptStudyInterfaceObject
TypeScript

[TypeScript] 객체(Object) 타입과 구조적 타이핑

November 26, 2025

이번에는 타입스크립트에서 객체(Object) 의 타입을 정의하는 방법과 구조적 타입 시스템, 그리고 선택적/읽기 전용 프로퍼티 같은 특수 문법에 대해 알아본다. 1. object 타입 타입스크립트에서 객체의 타입을 정의하는 가장 간단한 방법은 object 키워드를 사용하는 것이다. ts let user: object = { id: 1, name: "탬니", }; 하지만 이렇게 object로 타입을 정의하면 한 가지 치명적인 문제가 발생한다. ts // user.id; // ❌ 에러 발생 (Property 'id' does not exist on type 'object') 왜 에러가 날까?object 타입은 해당 변수가 '객체이다' 라는 사실만 알려줄 뿐, 그 객체 안에 어떤 프로퍼티가 있는지에 대한 정보는 전혀 없기 때문이다. 따라서 실제 프로퍼티에 접근하려고 하면 에러가 발생한다. 우리가 원하는 것은 객체의 구체적인 구조까지 타입으로 정의하는 것이다. 이때 사용하는 것이 바로 객체 리터럴 타입이다. 2. 객체 리터럴 타입 객체 리터럴 타입은 중괄호 {}를 열고, 객체가 가져야 할 프로퍼티의 이름과 타입을 직접 나열하여 정의한다. ts let user: { id: number; name: string; } = { id: 1, name: "탬니", }; console.log(user.id); // 1 (정상 작동) 이제 타입스크립트는 user 객체 안에 id가 숫자형이고, name이 문자열이라는 것을 정확히 인지한다. 점 표기법을 사용할 때 자동 완성이 지원되고, 타입 검사도 수행된다. 구조적 타입 시스템 (Structural Type System) 여기서 알 수 있는 중요한 사실은, 타입스크립트가 프로퍼티를 기준으로 객체의 타입을 정의한다는 점이다. - 명목적 타입 시스템 (Nominal Type System): C, Java처럼 클래스나 인터페이스의 '이름'을 기준으로 타입을 따지는 방식. - 구조적 타입 시스템 (Structural Type System): 타입스크립트처럼 이름이 무엇이든 "어떤 구조(프로퍼티)를 가지고 있느냐" 를 기준으로 타입을 따지는 방식. 마치 "이름(name)과 색깔(color)이 있으면 그건 강아지 객체야"라고 판단하는 것과 같다. 이를 프로퍼티 베이스드 타입 시스템(Property-based Type System) 이라고도 부른다. ts let dog: { name: string; color: string; } = { name: "뽀삐", color: "white", }; 3. 특수한 프로퍼티 정의하기 객체 타입을 정의할 때 상황에 따라 프로퍼티를 선택적으로 만들거나, 수정할 수 없게 만들 수 있다. 3-1. 선택적 프로퍼티 (Optional Property) 객체를 다루다 보면 특정 프로퍼티가 있을 수도 있고 없을 수도 있는 경우가 있다. 예를 들어 이름은 있지만 id는 아직 발급되지 않은 유저가 있을 수 있다. 이때 프로퍼티 이름 뒤에 물음표(?) 를 붙여주면 된다. ts let user: { id?: number; // 있어도 되고 없어도 됨 name: string; } = { id: 1, name: "탬니", }; // id가 없는 객체를 할당해도 에러가 나지 않음 user = { name: "홍길동", }; 주의할 점: 선택적 프로퍼티라 하더라도, 만약 값이 존재한다면 반드시 정의된 타입(number)이어야 한다. 엉뚱한 타입(string 등)을 넣으면 에러가 발생한다. 3-2. 읽기 전용 프로퍼티 (Readonly Property) API 키나 고유 ID처럼, 객체 생성 시 한 번 값이 정해지면 절대 바뀌면 안 되는 값들이 있다. 이때는 프로퍼티 이름 앞에 readonly 키워드를 붙인다. ts let config: { readonly apiKey: string; // 읽기 전용 } = { apiKey: "my-secret-key", }; // config.apiKey = "hacked"; // ❌ 에러 발생 (읽기 전용 속성이므로 할당 불가) readonly를 사용하면 의도치 않게 중요한 데이터가 수정되는 것을 코드 레벨에서 방지할 수 있다. --- 요약 1. object 타입: 단순히 "객체임"만 명시하므로 프로퍼티 접근이 불가능하다. 지양하는 것이 좋다. 2. 객체 리터럴 타입: { key: type } 형태로 구조를 명확히 정의한다. (구조적 타이핑) 3. 선택적 프로퍼티 (?): 해당 프로퍼티가 없어도 에러가 나지 않는다. 4. 읽기 전용 프로퍼티 (readonly): 초기화 이후 값을 수정할 수 없다.

TypeScriptStudy기초문법Object