Exported on 2025. 8. 6. at 1시 29분 0초 GMT+9 from Cursor (1.3.9)
User
나는 리액트 초보고 너는 교수님이야. 너는 이해 못하는 나에게 이해할 수 있도록 설명해줘야해. 내가 products.ts에 Products 상수를 export했는데, App.tsx에서 ProductWithUI로 되어있는것을 상수를 import해서 치환해주려고 하는데 왜 typeof Products[number]를 써야 문법오류가 안나는지 궁금해. Products를 그대로 쓸 수 없는거야?
Cursor
좋은 질문이야! 이건 TypeScript의 타입 시스템을 이해하는 데 중요한 개념이야. 차근차근 설명해줄게.
이제 이해했어! 너의 질문에 대해 차근차근 설명해줄게.
Products
를 그대로 쓰면 안 되는 이유// ❌ 이렇게 하면 안 돼
const addProduct = useCallback(
(newProduct: Omit<Products, 'id'>) => { // 에러!
// ...
},
[addNotification],
);
왜 안 될까?
Products
는 배열이야. ProductWithUI[]
타입이지.typeof Products[number]
가 뭔가?이건 TypeScript의 인덱스 접근 타입(Indexed Access Types)이야.
// Products 배열에서 하나의 요소 타입을 가져오는 방법
typeof Products[number]
분해해서 설명하면:
typeof Products
: Products 변수의 타입 (ProductWithUI[]
)[number]
: 배열의 인덱스 접근자typeof Products[number]
: 배열에서 하나의 요소 타입 (ProductWithUI
)// 방법 1: typeof Products[number] (현재 사용 중)
const addProduct = useCallback(
(newProduct: Omit<(typeof Products)[number], 'id'>) => {
// ...
},
[addNotification],
);
// 방법 2: 직접 타입 사용
const addProduct = useCallback(
(newProduct: Omit<ProductWithUI, 'id'>) => {
// ...
},
[addNotification],
);
// 방법 3: 배열 타입에서 추출
type ProductType = (typeof Products)[number];
const addProduct = useCallback(
(newProduct: Omit<ProductType, 'id'>) => {
// ...
},
[addNotification],
);
typeof Products[number]
를 썼을까?장점:
1. 타입 동기화: Products
배열이 변경되면 자동으로 타입도 업데이트
2. 단일 진실 공급원: 타입 정의를 한 곳에서만 관리
3. 실수 방지: 배열과 타입이 일치하지 않는 실수 방지
// products.ts
export const Products: ProductWithUI[] = [
{
id: 'p1',
name: '상품1',
price: 10000,
// ...
},
// ...
];
// App.tsx
const addProduct = useCallback(
(newProduct: Omit<(typeof Products)[number], 'id'>) => {
// newProduct는 이렇게 생겼어:
// {
// name: string;
// price: number;
// stock: number;
// description?: string;
// isRecommended?: boolean;
// discounts: Discount[];
// }
// (id는 제외됨)
},
[addNotification],
);
Products
는 배열이니까 직접 사용할 수 없어typeof Products[number]
는 배열에서 하나의 요소 타입을 가져오는 방법이해됐어? 더 궁금한 게 있으면 언제든 물어봐! 😊
// ❌ 이렇게 하면 안 돼
const addProduct = useCallback(
(newProduct: Omit<Products, 'id'>) => { // 에러!
// ...
},
[addNotification],
);
// Products 배열에서 하나의 요소 타입을 가져오는 방법
typeof Products[number]
// 방법 1: typeof Products[number] (현재 사용 중)
const addProduct = useCallback(
(newProduct: Omit<(typeof Products)[number], 'id'>) => {
// ...
},
[addNotification],
);
// 방법 2: 직접 타입 사용
const addProduct = useCallback(
(newProduct: Omit<ProductWithUI, 'id'>) => {
// ...
},
[addNotification],
);
// 방법 3: 배열 타입에서 추출
type ProductType = (typeof Products)[number];
const addProduct = useCallback(
(newProduct: Omit<ProductType, 'id'>) => {
// ...
},
[addNotification],
);
// products.ts
export const Products: ProductWithUI[] = [
{
id: 'p1',
name: '상품1',
price: 10000,
// ...
},
// ...
];
// App.tsx
const addProduct = useCallback(
(newProduct: Omit<(typeof Products)[number], 'id'>) => {
// newProduct는 이렇게 생겼어:
// {
// name: string;
// price: number;
// stock: number;
// description?: string;
// isRecommended?: boolean;
// discounts: Discount[];
// }
// (id는 제외됨)
},
[addNotification],
);