9월 프리온보딩 프론트엔드 챌린지
· 약 6분
9월 프리온보딩 프론트엔드 챌린지 수강 도중 애매하게 알고 있었거나 새로이 알게된 정보 정리합니다.
타입스크립트
타입스크립트 공식 문서
1. soundness
- 건전성에 대한 참고 사항
- 건전성. 형식 체계 내에서 증명 가능한 명제가 의미론 상으로도 참이 되는 성질.
- 타입스크립트에는 soundness가 있는데 대표적으로 type assertion 이 있다.
const usersAge = ("23" as any) as number;- 타입스크립트는 런타임에 개입하지 않기 때문에 (이는 soundness 특성 때문) 개발자는 Narrowing으로 타입을 좁혀주어야 한다.
2. unknown
- 이 타입이 어떤 타입인지 개발자도 아직 모를 때
- any와 비슷하지만 unknown의 가장 큰 특징은 에러를 발생시킨다는 것에 있다.
- 타입가드를 사용하자.
let num: unknown = 99;
if (typeof num === 'string') {
num.trim();
}
(num as string).trim();
const jsonParserUnknown = (jsonString: string): unknown =>
JSON.parse(jsonString);
type User = { name: string };
const myUserAccount = jsonParserUnknown(`{ "name": "Samuel" }`) as User;
myUserAccount.name;
3. 구조적 서브 타이핑을 기반으로 하는 타입스크립트
구조적 타입
- 사실 타입스크립트의 타입은 집합의 일부일 수 있다. 즉 언어가 집합의 관계를 따진다.
- 객체가 어떤 속성들을 가지는지 구조를 기준으로 타입을 따진다.
- 타입의 생김새가 오리와 같다면 바로 오리의 타입임을 뜻한다.
- 오리처럼 보이고, 오리처럼 수영하고, 오리처럼 꽥꽥거리면 그것은 오리일 것이다.
- 거위가 오리와 같은 속성을 가지고 있다면 그것조차도 오리 타입
- 일반적으로 동적 타입 시스템을 설명하는 데 덕 타이핑이 사용된다.
명목적 타입
- 각 타입이 고유하다는 것을 의미.
- 즉 동일한 타입이나 데이터가 있더라도 타입을 공유할 수 없다.
- 이름 기반으로 타입을 따진다
- 작성한 타입이 런타임에 존재한다.
- C#, Java
타입스크립트 활용
1. TS 컨벤션 참조 사이트
2. 어떤 객체의 value가 false값만 들어온다면, 타입스크립트로도 최대한 좁혀서 사용한다.
- 어떤 todo가 만들어질 때, 처음에
isCompleted는 무조건 false로 들어온다.
interface CreateTodo {
id: string;
content: string;
isCompleted: boolean; // <- 여기
category?: string;
tags?: string[];
}
const createTodo = ({ content, category, tags }: CreateTodo): CreateTodo => {
return {
id: String(new Date()),
isCompleted: false,
content,
category,
tags,
};
};
- 위 코드의 isCompleted는 boolean으로 타입지정이 되어있지만 이는 좋은 코드가 아니다.
interface CreateTodo {
id: string;
content: string;
isCompleted: false;
category?: string;
tags?: string[];
}
const createTodo = ({ content, category, tags }: CreateTodo): CreateTodo => {
return {
id: String(new Date()),
isCompleted: false,
content,
category,
tags,
};
};
- 확장을 사용하여 위 코드보다 더 좋게 만들어보자.
interface Todo {
id: string;
content: string;
isCompleted: boolean;
category: string;
tags: string[];
}
interface CreateTodo extends Todo {
isCompleted: false;
}
const createTodo = ({ content, category, tags }: CreateTodo): CreateTodo => {
return {
id: String(new Date()),
isCompleted: false,
content,
category,
tags,
};
};
3. 자주 사용하는 type은 최대한 재활용해서 쓰는 게 좋다.
interface Todo {
id: string;
content: string;
isCompleted: boolean;
category?: string;
tags: string[];
}
interface DeleteTagParamsType {
id: string;
tagIdx?: number;
}
- 위 코드의 문제는, id가 string이 아닌 다른 타입으로 바뀔 때 일어난다. 아래처럼 바꾼다면 좀 더 안정적으로 타입을 지정할 수 있다.
interface Todo {
id: string;
content: string;
isCompleted: boolean;
category?: string;
tags: string[];
}
interface DeleteTagParamsType {
id: Todo['id'];
tagIdx?: number;
}
- 이렇게 하면 id의 타입이 바뀌어도 손쉽게 수정할 수 있다.
- 아래처럼 typescript 유틸리티를 사용할 수도 있다. (Omit, Pick...)
interface Todo {
id: string;
content: string;
isCompleted: boolean;
category?: string;
tags: string[];
tagIdx?: number;
}
type shoppingItem = Pick<Todo, 'tagIdx'>;
- 확장을 사용할 수도 있다.
interface Todo {
id: string;
content: string;
isCompleted: boolean;
category?: string;
tags: string[];
}
interface DeleteTagParamsType extends Todo {
tagIdx?: number;
}
4. 함수형 type을 지정할때 void가 return 되는 type이 많다면, 한 번 의심해보는 게 좋다.
- 함수가 너무 많은 일을 하고 있을 수 있으므로 점검해보자