TypeScript에서 No index signature오류 해결하기

명확하게 하지 않으면 타입스크립트를 사용할 때 마다 해당 오류를 만나는 거 같아 근본적인 원인을 글로 정리했습니다.

오류의 코드

const MIME_TYPE_MAP = {
  "image/png": "png",
  "image/jpg": "jpg",
  "image/jpeg": "jpeg",
};

const file = { mimetype: "image/png" };
const ext = MIME_TYPE_MAP[file.mimetype]; //  TypeScript 오류 발생
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ "image/png": string; "image/jpg": string; "image/jpeg": string; }'.
  No index signature with a parameter of type 'string' was found on type '{ "image/png": string; "image/jpg": string; "image/jpeg": string; }'.

오류의 원인

TypeScript는 객체의 키를 엄격한 리터럴 타입으로 추론, 즉, MIME_TYPE_MAP의 키는 정확히 “image/png” | “image/jpg” | “image/jpeg”로 제한된다.

하지만, file.mimetype의 타입은 일반적으로 string이므로, TypeScript는 “image/png” | “image/jpg” | “image/jpeg” 이외의 값이 들어올 가능성이 있다고 판단

어떻게 수정해야 하는가

file.mimetype의 타입을 MIME_TYPE_MAP의 키로 제한

const MIME_TYPE_MAP = {
  "image/png": "png",
  "image/jpg": "jpg",
  "image/jpeg": "jpeg",
};

const file: { mimetype: keyof typeof MIME_TYPE_MAP } = { mimetype: "image/png" }; // mimetype이 존재하는 경우
const ext = MIME_TYPE_MAP[file.mimetype];
console.log(ext); // "png"

file.mimetype의 타입을 정확하게 제한

const MIME_TYPE_MAP = {
  "image/png": "png",
  "image/jpg": "jpg",
  "image/jpeg": "jpeg",
};

const file: { mimetype: "image/png" | "image/jpg" | "image/jpeg" } = { mimetype: "image/png" };
const ext = MIME_TYPE_MAP[file.mimetype];

MIME_TYPE_MAP을 더 유연한 형태로 정의 (Record 사용)

const MIME_TYPE_MAP: Record<string, string> = {
  "image/png": "png",
  "image/jpg": "jpg",
  "image/jpeg": "jpeg",
};

Leave a Comment