[TypeScript] Ch4. 객체

bin·2023년 6월 6일
0
post-thumbnail

객체

객체 리터럴은 각자의 타입이 있는 키와 값의 집합

구조적 타이핑

타입스크립트의 타입 시스템은 구조적으로 타입화 되어 있다.
즉, 타입을 충족하는 모든 값을 해당 타입의 값으로 사용할 수 있다.

type WithFirstName = {
	firstName: string;
};

type WithLastName = {
	lastName: string;
};

const hasBoth = {
	firstName: "Lucille",
  	lastName: "Clifton",
};

// OK: 'hasBoth'는 'string' 타입의 firstName을 포함함 
let withFisrtName: WithFirstName = hasBoth;

// OK: 'hasBoth'는 'string' 타입의 lastName을 포함함 
let withLastName: WithLastName = hasBoth;

덕 타이핑 (Duck Typing)

런타임에서 사용될 때까지 객체 타입을 검사하지 않는 것
-> JavaScript는 덕 타입인 반면 TypeScript는 구조적으로 타입화 된다.

선택적 속성

타입의 속성 애너테이션에서 : 앞에 ? 를 추가하면 선택적 속성임을 나타낼 수 있다.
선택적 속성은 존재하지 않아도 되지만, 필수로 선언된 속성과 | undefined는 그 값이 undefined일지라도 반드시 존재해야 한다.

type Writers = {
	author: string | undefined;
  	editor?: string;
};

// editor는 선택적 속성이므로 반드시 존재하지 않아도 된다.
const hasRequired: Writers = {
	author: undefined,
};

// Error 
const missingRequired: Writers = {}; 

객체 타입 유니언

유추된 객체 타입 유니언

변수에 여러 객체 타입 중 하나가 될 수 있는 초깃값이 주어지면 타입스크립트는 해당 타입을 객체 타입 유니언으로 유추한다.

const poem = Math.random() > 0.5
	? { name: "The Double Image", pages: 7 }
	: { name: "Her kind", rhymes: true };

// 타입 : 
// {
// 		name: string; 
//  	pages: number;
//   	rhymes?: undefined;
// }
// |
// {
// 		name: string;
//  	pages?: undefined;
// 		rhymes: boolean;
// }

명시된 객체 타입 유니언

다음과 같이 객체 타입의 조합을 명시하면 객체 타입을 더 명확히 제어할 수 있어 코드의 안전을 지킬 수 있다.

type PoemWithPages = {
	name: string;
  	pages: number;
};

type PoemWithRhymes = {
	name: string;
  	rhymes: boolean;
};

type Poem = PoemWithPages | PoemWithRhymes;

const poem: Poem = Math.random() > 0.5
	? { name: "The Double Image", pages: 7 }
	: { name: "Her Kind", rhymes: true };

// name 속성은 항상 존재하기 때문에 허용, 나머지 pages와 rhymes 속성은 항상 존재한다는 보장이 없으므로 접근 불가
poem.name; // OK
poem.pages; // Error 
poem.rhymes; // Error 

판별된 유니언

객체의 속성이 객체의 형태를 나타내도록 하는 타입 형태를 판별된 유니언이라 부르고, 객체의 타입을 가리키는 속성이 판별값이다.

type PoemWithPages = {
	name: string;
  	pages: number;
  	type: 'pages';
};

type PoemWithRhymes = {
	name: string;
  	rhymes: boolean;
  	type: 'rhymes';
};

type Poem = PoemWithPages | PoemWithRhymes;

const poem: Poem = Math.random() > 0.5
	? { name: "The Double Image", pages: 7 }
	: { name: "Her Kind", rhymes: true };

if(poem.type === "pages") {
	poem.pages; // 타입 내로잉을 통해 값에 존재하는 속성이 보장되므로 해당 속성에 접근 가능  
} else {
  	poem.rhymes;
}

교차 타입 (Intersection Type)

& 교차 타입을 사용해 여러 타입을 동시에 나타낼 수 있다.

type Artwork = {
	genre: string;
  	name: string;
};

type Writing = {
	pages: number;
  	name: string;
};

type WrittenArt = Artwork & Writing; // genre, name, pages 속성을 모두 가지게 된다. 

교차 타입의 위험성

  • 긴 할당 가능성 오류
    복잡한 교차 타입을 만들면 오류 메시지의 가독성이 떨어진다. 타입을 일련의 별칭으로 된 객체 타입으로 분할하면 읽기가 훨씬 쉬워진다.
type ShortPoemBase = { authrot: string };

// 분할
type Haiku = ShortPoemBase & { kigo: string; type: "haiku" };
type Villanelle = ShortPoemBase & {  meter: number; type: "villanelle" };

type ShortPoem = Haiku | Villanelle

const oneArt: ShortPoem = { // Error 
	author: "Elizabeth Bishop",
  	type: "villanelle"
}
  • never
    never 키워드와 never 타입은 bottom 타입 또는 empty 타입을 뜻한다. bottom 타입은 값을 가질 수 없고 참조할 수 없는 타입이므로 어떠한 타입도 제공할 수 없다.

5개의 댓글

comment-user-thumbnail
2023년 6월 16일

안녕하세요

1개의 답글