→ 값의 속성에 접근하려면 value.멤버 또는 value[’멤버’] 구문 사용
const pet = {
born: 2008,
name: "ari"
}
pet['born']; //타입 number
pet.name //타입 string
// pet.end;
//Property 'end' does not exist on type '{ born: number; name: string; }'
* 객테 타입의 선언
→ 명시적 선언
→ 객체 리터럴과 유사해보이나 필드 값 대신 타입 사용
let pets: {
born: number;
name: string;
}
pets = {
born: 2008,
name: "ari"
}
// pets = "ari";
//Type 'string' is not assignable to type '{ born: number; name: string; }'
* 별칭 객체 타입
→ 타입스크립트의 타입 시스템을 배울 때, 타입스크립트가 객체 리터럴을 해석하는 방법을 이해하는 것은 매우 중요함
type pets = { //타입으로 작성
born: number;
name: string;
}
let laterPets: pets;
laterPets = {
born: 2008,
name: "ari"
}
// laterPets = "ari";
//Type 'string' is not assignable to type 'pets'
* 구조적 타이핑
→ 구조적으로 타입화 : 타입을 충족하는 모든 값을 해당 타입의 값으로 사용 가능
(덕 타이핑(오리처럼 보이고 오리처럼 꽥꽥이면 오리일 것과는 다름)
→ 자바스크립트는 덕 타입, 타입스크립트는 구조적으로 타입화
type WithFirstName = {
firstName: string;
}
type WithLastName = {
lastName: string;
}
const hasBoth = {
firstName: "백호",
lastName: "강",
}
let withFirstName: WithFirstName = hasBoth;
let withLastName: WithLastName = hasBoth;
* 사용 검사
→ 객체 타입으로 애너테이션 위치에 값을 제공할 때 타입스크립트는 값을 해당 객체 타입에 할당 할 수 있는지 확인
→ 할당하는 값에는 객체 타입의 필수 속성이 있어야 함
type FisrtAndLstNames = {
first: string;
last: string;
}
const hasBoth: FisrtAndLstNames = {
first: "백호",
last: "강"
}
const hasOnlyOne: FisrtAndLstNames = {
first: "태웅"
//Property 'last' is missing in type '{ first: string; }' but required in type 'FisrtAndLstNames'.
}
type TimeRange = {
start: Date;
}
const hasStartString: TimeRange = {
start: "1996-01-31"; //오류 type은 Date로 명시하나 실제 값은 string
}
* 초과 속성 검사
→ 변수가 객체 타입으로 선언, 초기값에 정의된 것보다 많은 필드 존재 시 오류 발생
→ 변수를 객체타입으로 선언하는 것 : 타입 검사기가 해당 타입에 예상되는 필드만 있는지 확인
type pets = { //타입으로 작성
born: number;
name: string;
}
const petMatch: pets = {
born: 2008,
name: "ari"
}
const extraPet: pets = { //오류 발생
activity: "walking",
//Type '{ activity: string; born: number; name: string; }' is not assignable to type 'pets'.
//Object literal may only specify known properties, and 'activity' does not exist in type 'pets'
born: 2008,
name: "ari"
}
const existingObject = {//오류 없음
activity: "walking",
born: 2008,
name: "ari"
}
const extraPropertyButOk: Pets = existingObject;
//초기값이 구조적으로 Pets와 일치하기 때문
* 중첩된 객체 타입
→ 중첩된 객체 타입을 고유한 타입 이름으로 바꿔서 사용 시 코드와 오류 메시지를 더 읽기 쉬워짐
type Poem = {
author: {
firstName: string;
lastName: string;
};
name: string;
}
const poemMatch: Poem = {
author: {
firstName: "소월",
lastName: "김",
},
name: "한용운"
};
const poemMismatch: Poem = {
author: {
name: "김소월",
//Type '{ name: string; }' is not assignable to type '{ firstName: string; lastName: string; }'.
//Object literal may only specify known properties, and 'name' does not exist in type '{ firstName: string; lastName: string; }'
}
name: "진달래"
}
* 선택적 속성
→ 모든 객체에 객체 타입 속성이 필요한 것은 아님
→ 타입의 속성 애너테이션에서 앞에 ? 추가
type Book = {
author?: string;
pages?: number;
}
const ok: Book = {
author: "김소월",
pages: 80,
}
const missing: Book = {
author: "김소월"
//pages가 없어도 오류 없음
}
* 속성이 조금 다른, 하나 이상의 서로 다른 객체 타입이 될수 있는 타입 설명할 수 있어야 함
* 유추된 객체 타입 유니언
→ 변수에 여러 객체 타입 중 하나가 될 수 있는 초기값이 주어지면 타입스크립트는 해당 타입을 객체 타입 유니언으로 유추
const poem = Math.random() > 0.5
? { name : "윌리엄 셰익스피어", pages: 500 }
: { name : "조지 오웰", rhymes: true }
//타입
// {
// name: string;
// pages: number;
// rhymes?: undefined;
// }
// {
// name: string;
// pages: number;
// rhymes?: boolean;
// }
// {
// name: string;
// pages: number;
// rhymes?: booleans | undefined;
// }
* 명시된 객체 타입 유니언
→ 값의 타입이 객체 타입으로 구성된 유니언이라면 모든 유니언 타입에 존재하는 속성에 대한 접근만 허용됨
→ 속성 name에 접근하는 것은 name속석이 항상 존재하기 때문에 허용되나 pages와 ryhmes는 항상 존재한다는 보장이 없음
→ 리터럴 타입이나 원시 타입 모두, 혹은 둘 중 하나로 이루어진 유니언 타입에서 모든 타입에 존재하지 않은 속성에 접근 시 타입을 좁혀야 하는 것처럼 객체 타입 유니언도 타입을 좁혀야 함
type PoemWithPages = {
name: string;
pages: number;
}
type PoemWithRhymes = {
name: string;
rhymes: boolean;
}
type Poem = PoemWithPages | PoemWithRhymes;
const poem: Poem = Math.random() > 0.5
? { name : "윌리엄 셰익스피어", pages: 500 }
: { name : "조지 오웰", rhymes: true };
console.log(poem.name);
//"The Double Image"
//"Her Kind"
console.log(poem.pages) //오류
//Property 'pages' does not exist on type 'Poem'
* 객체 타입 내로잉
→ 코드에서 객체의 형태를 확인하고 타입 내로잉이 객체에 적용됨
type PoemWithPages = {
name: string;
pages: number;
}
type PoemWithRhymes = {
name: string;
rhymes: boolean;
}
type Poem = PoemWithPages | PoemWithRhymes;
const poem: Poem = Math.random() > 0.5
? { name : "윌리엄 셰익스피어", pages: 500 }
: { name : "조지 오웰", rhymes: true };
console.log(poem.name);
if("pages" in poem) {
poem.pages; //poem은 PoemWithPages로 좁혀짐
} else {
poem.rhymes; //poem은 PoemWithRhymes로 좁혀짐
}
* 판별된 유니언
→ 유니언 타입으로 된 객체의 또 다른 인기 있는 형태 = 객체의 속성이 객체의 형태를 나타나도록 함
→ 타입 형태 : 판별된 유니언, 객체의 타입을 가리키는 속성 : 판별
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 : "윌리엄 셰익스피어", pages: 500, type: "pages" }
: { name : "조지 오웰", rhymes: true, type: 'rhymes' };
if(poem.type === "pages") {
console.log(`영국 작가의 페이지: ${poem.pages}`)
} else {
console.log(`It's rhymes: ${poem.rhymes}`)
}
poem.type; //type: "pages" | "rhymes"
poem.pages;
//Property 'pages' does not exist on type 'Poem'.
// Property 'pages' does not exist on type 'PoemWithRhymes'.
* 유니언 타입 : 둘 이상의 다른 타입 중 하나의 타입이 될 수 있음 나타냄
→ 자바스크립트 : | , 타입스크립트 & 교차 타입
→ 교차 타입은 유니언 타입과 결합 가능, 하나의 타입으로 판별된 유니언 타입 설명 시 유용
type Artwork = {
genre: string;
name: string;
}
type Writing = {
pages: number;
name: string;
}
type WrittenArt = Artwork & Writing;
// {
// genre: string;
// name: string;
// pages: number
// }
type ShortPoem = { author: string } & (
| { name : string; type : 'drama';}
| { meter: number; type: 'movie' }
)
const moringGlory: ShortPoem = {
author : "김은숙",
name: "The Glory",
type: 'drama'
}
const oneArt: ShortPoem = {
//Type '{ author: string; type: "movie"; }' is not assignable to type 'ShortPoem'.
//Type '{ author: string; type: "movie"; }' is not assignable to type '{ author: string; } & { meter: number; type: "movie"; }'.
author: "이노우에 다케히코,
type: "movie"
}
* 교차 타입의 위험성
→ 타입스크립트 컴파일러를 혼동시키는 방식으로 사용하기 쉬움
→ 가능한 간결하게 코드 유지
type ShortPoemBase = { author : string };
type Haiku = ShortPoemBase & { name : string; type: "drama" };
type Villanella = ShortPoemBase & { meter: number; type: "movie" };
type ShortPoem = drama | movie;
const oneArt: ShortPoem = {
//Type '{ author: string; type: "movie"; }' is not assignable to type 'ShortPoem'.
//Type '{ author: string; type: "movie"; }' is not assignable to type 'Villanella'.
author: "이노우에 다케히코",
type: "movie"
}
* never
→ 교차 타입은 잘못 사용하기 쉽고 불가능한 타입 생성
→ 두 개의 원시 타입을 함께 시도 시 never 키워드로 표시되는 never 타입됨
type NotPossible = number & string; //never
let notNumber: NotPossible = 0;
//Type 'number' is not assignable to type 'never'
let notString: never = "";
//Type 'string' is not assignable to type 'never'