
[2025. 03. 10. 월요일]
ts에서 타입을 변수처럼 사용하는 제네릭타입에 대해서
React에서 많이 사용하는 useState를 예시로 이해하기!!
const [state, setState] = useState<T>([])
- useState는
(초기값)을 받아서[state, setState]를 반환한다.- 초기값은 state에 할당되고, setState함수는
(newState)를 받아서 state에 newState를 재할당한다.
const useState<T> = (initialState: T): [T, (newState: T)=>void] => {
let state = initialState // 초기값을 state에 할당
const setStste = (newState: T) => {
// 리렌더링
state = [...state, newState] // newState를 state에 재할당
// 추가 로직들...
}
return [state, setState] // state배열을 반환
}
이 과정중에서 내부 로직을 보면 초기값의 타입과 내부 로직의 타입들이 일치해야 타입스크립트에서 오류없이 useState훅이 동작할 수있다.
타입스크립트에서 각 타입을 명시해야하는 곳들을 보면 여러곳이다. 매번 타입을 작성해주는 것도 번거롭지만, 처음에 <number>로 타입을 명시 했다가 <string>으로 바꾼다고 생각을 해보면 이과정이 더 번거롭게 된다.
타입이 명시될 위치에 <T>라고 제네릭타입으로 적어주면 내부 로직 모든 곳에서 변수처럼 동일한 타입을 받을 수 있다.
- 로직 내부적으로
<T>재사용가능하며 중복코드를 줄일 수있다.- 아직 결정되지 않은 Type으로 어떤타입도 받을 수 있는 변수처럼 취급할 수 있기 때문에 유연하다.
- 함수가 호출될 때 타입이 결정되며 반환값도 인자타입과 동일하기 때문에 안정성도 있다.
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo, 'title' | 'completed'>;
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
};
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Omit<Todo, 'description'>;
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
};
type PageInfo = {
title: string;
};
type Page = 'home' | 'about' | 'contact';
const pages: Record<Page, PageInfo> = {
home: { title: "Home Page" },
about: { title: "About Page" },
contact: { title: "Contact Page" },
};
타입을 명시해줘야하는 타입스크립트를 배우면서 굳이 타입을 작성해 줘야 하나? 하는 의문도 많고 부담이 됐는데, 어려웠던 제네릭을 어느정도 이해하니 조금은 타입을 명시하는 이유를 알것같기도 하다.