객체 타입은 객체의 형태
를 설명하는 방법이다.
:
을 사용하고 속성의 타입을 설명;
으로 구분=
를 사용,
로 구분// 객체 타입
let friend: {
name: string;
age: number;
hasJob: boolean;
}
// 객체 리터럴
friend = {
name: "harry",
age: 12,
hasJob: true,
}
friend = "ron";
// Error: Type 'string' is not assignable to type '{ name: string; age: number, hasJob: boolean }'
객체 타입을 사용하는 것보다 타입 별칭(type alias)를 사용하는 것이 편리하다.
또한 오류 메세지가 보다 더 직관적이다.
type Person: {
name: string;
age: number;
hasJob: boolean;
}
let friend: Person;
friend = {
name: "harry",
age: 12,
hasJob: true,
}
friend = "ron";
// Error: Type 'string' is not assignable to 'Person'.
type FullName = {
firstName: string;
lastName: string;
};
const hasBoth: FullName = {
firstName: "Harry",
lastName: "Potter",
};
const hasOnlyOne: FullName = {
firstName: "Ron",
}
// Property 'lastName' is missing in type '{ firstName: string; }' but required in type 'FullName'.
객체 타입으로 명시한 변수에 값을 할당할 때, 그 값에는 객체 타입의 필수 속성들이 모두 포함되어야 한다.
객체 타입의 필수 속성들이 모두 명시되지 않은 값을 할당시키면 타입스크립트는 에러를 발생시킨다.
type FullName = {
firstName: string;
lastName: string;
};
const hasBoth: FullName = {
firstName: "Harry",
lastName: "Potter",
};
const hasOnlyOne: FullName = {
firstName: "Ron",
lastName: "Weasley",
age: 30, // ❌
}
// Type '{ firstName: string; lastName: string; age: number; }' is not assignable to type 'FullName'.
// Object literal may only specify known properties, and 'age' does not exist in type 'FullName'.
type Book = {
author: {
firstName: string;
lastName: string;
};
title: string;
};
const HarryPotter: Book = {
author: {
firstName: "JK",
lastName: "Rowling",
},
title: "Goblet of Fire",
};
const NoTitle: Book = { // ❌
author: {
firstName: "John",
lastName: "Doe",
}
}
// Property 'title' is missing in type '{ author: { firstName: string; lastName: string; }; }' but required in type 'Book'.
객체 타입의 속성 값이 객체 타입(중첩된 객체 타입)인 경우 type alias를 사용하면 코드의 가독성이 높아지고, 에러 메세지 또한 읽기 쉬워진다.
type Author = {
firstName: string;
lastName: string;
};
type Book = {
author: Author; // ⭕️
title: string;
};
const HarryPotter: Book = {
author: {
firstName: "JK",
lastName: "Rowling",
},
title: "Goblet of Fire",
};
const NoTitle: Book = {
author: { // ❌
firstName: "John",
}
}
// Property 'lastName' is missing in type '{ firstName: string; }' but required in type 'Author'.
타입의 속성 뒤에 ?
를 추가하면 옵셔널 프로퍼티로 나타낼 수 있다.
옵셔널 프로퍼티는 말 그대로 옵셔널(있어도 되고 없어도 되는)한 속성이다.
type Person = {
name: string;
age: number;
job?: string;
};
const friend: Person = {
name: "Harry",
age: 20,
};
const enemy: Person = { // ❌
age: 12,
job: "Death Eaters",
}
// Property 'name' is missing in type '{ age: number; job: string; }' but required in type 'Person'.
만약 필수 속성의 타입이
undefined
인 경우, 반드시 해당 속성을 명시하고 값 또한undefined
라고 명시해야 한다.
잠재적으로 존재하지 않는 객체의 멤버에 대한 접근을 제한하면 코드의 안전을 지킬 수 있습니다.
(러닝 타입스크립트, p91)
있을 수도, 없을 수도 있는 속성을 제한하지 않으면 예기치 못한 에러가 발생할 수 있다.
객체 타입 유니언을 명시적으로 작성하면 이것에 대한 에러를 방지할 수 있다.
type Student = {
name: string;
school: string;
}
type Employee = {
name: string;
company: string;
}
type Person = Student | Employee;
const friend: Person = Math.random() > 0.5
? { name: "Harry", school: "Hogwarts" }
: { name: "Cornelius", company: "Ministry of Magic" };
friend.name; // ⭕️
friend.company; // ❌
// Property 'company' does not exist on type 'Person'.
// Property 'company' does not exist on type 'Student'.
if (”속성” in 타입명시된변수)
type Student = {
name: string;
school: string;
}
type Employee = {
name: string;
company: string;
}
type Person = Student | Employee;
const friend: Person = Math.random() > 0.5
? { name: "Harry", school: "Hogwarts" }
: { name: "Cornelius", company: "Ministry of Magic" };
// 객체 타입 내로잉
if ("school" in friend) { // 여기서 school이 타입 가드의 역할을 한다.
friend.school; // ⭕️
} else {
friend.company; // ⭕️
}
유니언 타입이 or(|
)의 개념이라면, 교차 타입은 and(&
)의 개념이다.
여러 타입을 동시에 나타낸다.
여러 객체 타입을 합쳐서 하나의 type alias로 사용하는 것이 일반적인 교차타입이다.
원시 타입은 결합될 수 없다. 따라서 각기 다른 원시 타입을 교차 타입으로 결합시키면 never
타입이 된다.
아주 특정한 상황이 아닌 이상 거의 사용되지 않는다.
type NotPossible = number & string; // never type