반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- react fragment
- raect typescript #react #typescript #styled-component
- DP #c++
- React #리액트 이벤트 주기 #리액트 이벤트
- 이친수
- React #effect hook #useEffect
- interceptors
- RateLimit
- 노마드 코더 #타입스크립트 #typescript #class
- html entities
- React #controlled component #비제어 컴포넌트 #제어 컴포넌트
- 다익스트라 #파티 #백준
- 백준 #적록색약
- 백준 #직각삼각형
- 버블링 #갭쳐링 #이벤트 #JS
- npm #not being able to find a file #npm install Error
- useState #Hooks
- 코드스테이츠 #알고리즘 #그리디
- JWT #토큰 #refreshToken #accessToken #Token #token #localStorage #sessionStorage
- donwstream #upstream #origin
- 빡킹독
- #useRef #언제 쓰는데?
- react
- React #Hook rules #Hook 규칙
- 얕은 복사 #깊은 복사 #shallow copy #deep copy
- react #useCallback #react Hook
- axios
- 플로이드 #c++
- React-Query
- rate limit
Archives
- Today
- Total
꿈꾸는 개발자
4장 객체 본문
4.1 객체 타입
- {…}과 같이 객체 리터럴을 생성하면 TS는 해당 속성을 기반으로 새로운 객체 타입 또는 타입 형태를 고려한다. ⇒ 객체 값과 동일한 속성명 및 원시 타입을 갖는다.
const hoho={
born:1948,
name: "Mary",
}
hoho['born'] //number 타입
hoho.name //string 타입
hoho.end //에러 발생 (does not exist)
- 객체 타입은 TS가 JS코드를 이해하는 방법에 대한 핵심 개념이다. null과 undefined을 제외한 모든 값은 해당 값에 대한 실제 타입의 멤버 집합을 가짐(string, number 등 집합에 속함) ⇒ TS는 모든 타입의 값을 확인하기 위해 객체 타입을 이해해야 함
4.1.1 객체 타입 선언
- 명시적으로 객체 타입 선언하기 ⇒ 추가로, 객체의 형태를 설명하는 방법이 필요함
- 객체 타입은 필드 값 대신 타입을 사용해 설명
let hoho:{
born:number,
name: string,
}
hoho={
born:1934,
name: "mary",
}
hoho= "sldslf"; //string is not assignable to type {.....}
- born/name은 이전과 동일한 타입이지만, 위에서는 타입 명시를 통해 나타내줬음
4.1.2 별칭 객체 타입
- 객체 타입을 계속 작성하는 것보다 ⇒ 타입 별칭(call signature?)을 사용하는 것이 일반적
type ho={
born:number;
name:string;
};
let hoho:ho; //call signature으로 명시를 해줌
hoho={
born:1945,
name:"mary",
}
hoho="maymmay"; //string is not assignable to type {.....}
- 주의: 대부분의 TS 프로젝트에선 객체 타입을 설명할 때 인터페이스 keyword를 사용하는 것을 더 선호함 (인터페이스와 별칭 타입을 구별하는 것이 중요하다) ⇒ 그럼에도 별칭 타입을 배우는 이유: TS가 객체 리터럴을 해석하는 방법을 이해하는 것이 중요하기 때문
4.2 구조적 타이핑
TS의 타입 시스템은 구조적으로 타입화(strucally typed)돼 있음 ⇒ 타입을 충족하는 모든 값을 해당 타입의 값으로 사용 가능!
type FirstName={
first:string;
}
type LastName={
last:string;
}
const hasTwo={
first:"hoho",
last:"gogo",
}
//hasTwo는 string 타입의 first를 포함함.
let withFirstName:FirstName=hasTwo;
//hasTwo는 string 타입의 last를 포함함.
let withLastName:LastName=hasTwo;
- hasTwo는 타입 명시를 하진 않았지만, 두 개의 별칭 객체 타입을 다 가지고 있음 ⇒ 위처럼 사용이 가능함!
- 의문점: 그럼 withFristName은 “hoho”만 출력되는 것??
- 구조적 타이핑: 정적 시스템이 타입을 검사하는 경우
- 덕 타이핑: 런타임에서 사용될 때까지 객체 타입을 검사하지 않는 것을 말함
- JS: 덕 파이핑/ TS: 구조적 타이핑
4.2.1 사용 검사
- 객체 타입에 필요한 멤버가 없다면 TS는 타입 오류를 발생시킴
type FirstAndLastName={
first:string;
last:string;
}
const hasBoth:FirstAndLastName={
first:"abcde",
last:"asdfsd",
};
//FirstAndLastName는 first와 last 둘다 포함해야함
const hasOnlyOne: FirstAndLastName={
first:"asdfasdf",
}
- 일치하지 않는 타입도 허용하지 않는다
type Time={
first:string;
}
//타입 불일치에 따른 에러 발생함
const errortype:Time={
first:59,
}
4.2.2 초과 속성 검사
type Time={
born:number;
name:string;
}
const correctOne:Time={
born:59,
name:"Mary",
}
//타입보다 많기 대문에 에러가 발생함
const errorEx:Time={
activity:"walkring",
born:59,
name:"Mary",
}
- 객체 타입으로 선언된 것보다 더 많을 경우 에러 발생
const errorEx={
activity:"walkring",
born:59,
name:"Mary",
}
const extraPropertyButOk:Time=errorEx;
- 위와 같이 객체 타입으로 선언된 위치에서 생성되는 객체 리터럴이 아니면 초과 검사는 우회된다. ⇒ 배열, 클래스 필드, 함수 매개변수 모두 초과 속성이 일어난다.
4.2.3 중첩된 객체 타입
type Poem={
author:{
firstName:string;
lastName:string;
}
name:string;
};
const poemMatch:Poem={
author:{
firstName:"siva",
lastName:"plath",
},
name:"lady gaga",
};
//당연히 일치하지 않는 name이 들어있으니 에러 발생
const poemMismatch:Poem={
author:{
name:"siva path",
},
name:"tuple"
}
type Author={
firstName:string;
lastName:string;
}
type Poem={
author:Author
name:string;
};
- 위와 같이 객체 내 중첩되는 객체까지도 타입 객체로 축약할 수 있다.
4.2.4 선택적 속성
- 타입 속성 애너테이션: 앞에 ?를 추가하면 선택적 속성임을 나타낼 수 있다.
type Book={
author?:string;//있어도 되고 없어도 됨
pages:number;
}
const ok:Book={
author:"Hoin",
pages:80,
}
//객체 타입과 다르게 pages를 명시하지 않아서 에러가 발생함!
const missing:Book={
author:"hoin",
}
- ?를 사용해 선택적으로 선언된 속성은 필수가 아님!
- xxx | undefined의 형태의 경우 undefined으로 선언을 하더라도 무조건 존재해야 함을 의미 ?과 혼동하지 말 것!
4.3 객체 타입 유니언
- 하나 이상의 서로 다른 객체 타입이 될 수 있는 타입을 설명할 수 있어야 함
4.3.1 유추된 객체 타입 유니언
- 초깃값으로 선정될 수 있는 여러 객체 타입이 주어지면 TS는 해당 타입을 객체 타입 유니언으로 간주한다.
const poem=Math.random()>0.5 ?{name:"hello world", page:7}:{name:"theres", rhymes:true};
poem.name; //string
poem.page; // number | undefiend
poem.rhymes; //boolean | undefined
4.3.2 명시된 객체 타입 유니언:
- 객체 타입의 조합을 명시하면 객체 타입을 더 명확히 정의 가능, 특히 유니언 타입에 존재하는 속성에만 접근이 가능
type PoemWithPages={
name:string;
pages:number;
}
type PoemWithRhymes={
name:string;
rhymes:boolean;
}
type Poem= PoemWithPages | PoemWithRhymes;
const peom:Poem =Math.random()>0.5 ?{name:"hoin", pages:7}:{name:"otrhes",rhymes:true};
peom.name //둘 다 존재하기 때문에 에러 발생X
peom.pages //없을 수도 있기 때문에 에러가 발생한다.
- 잠재적으로 존재하지 않을 수도 있느 객체 멤버에 대한 접근 제한은 코드 안정성을 높인다. (객체 유니언에서 내로잉이 필요하다)
4.3.3 객체 타입 내로잉
if("pages" in peom){ //poem pages가 타입 가드의 역할을 함!
peom.pages;
}else{
peom.rhymes;
}
- TS에선 if(peom.pages)을 허용하지 않음, 존재 여부가 확실하지 않는 속성 접근 자체를 제한기 때문!
4.3.4 판별된 유니언
- 객체의 속성이 객체의 형태를 나타내도록 하는 것 ⇒ 객체 속성이 가리키는 속성이 판별값 (TS는 코드에서 판별 속성을 활용해 타입 내로잉을 함)
type PoemWithPages={
name:string;
pages:number;
type: 'pages';
}
type PoemWithRhymes={
name:string;
rhymes:boolean;
type:'rhymes';
}
type Poem= PoemWithPages | PoemWithRhymes;
const peom:Poem =Math.random()>0.5 ?{name:"hoin", pages:7, type:"pages"}:{name:"otrhes",rhymes:true,type:"rhymes"};
if(peom.type==="pages"){
console.log("its got pages: ");
}else{
console.log("it")
}
peom.type; //타입: 'pages' | 'rhymes'; 둘 중 하나!
4.4 교차 타입
**&**교차 타입을 사용해 여러 타입을 동시에 나타낼 수 있음 ⇒ 기존 객체 타입을 별칭 객체 타입으로 결합해 새로운 타입을 생성함
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}&(|{kigo:string; type:"haha"}|{meter:number; type:"vava"};);
//author은 항상 포함됨
const morning:ShortPoem={
author:"hoho",
kigo:"asdf",
type:"haha",
}
4.4.1 교차 타입의 위험성
교차 타입을 사용할 때 가능한 코드를 간결하게 유지하라!
긴 할당 가능성 오류
복잡한 교차 타입 ⇒ 할당 가능성 오류 메세지를 읽기 어렵게 됨
- 따라서 분할을 사용하면 훨씬 간결함
type ShortPoemBse={author:string};
type Haha= ShortPoemBse &{kigo:string; type:"haha"}
type Vava=ShortPoemBse&{meter:number; type:"vava"};
type ShortPoem=Haha | Vava;
//author은 항상 포함됨
const morning:ShortPoem={
author:"hoho",
kigo:"asdf",
type:"haha",
}
- 앞선 코드를 위와 같이 축약할 수 있음
never: 원시 타입의 결합은 시도하지 말 것!
Reference:
조시 골드버그, 러닝 타입스크립트, 고승원 옮김, 2023