본문 바로가기

내용 복습/Next.js

타입스크립트의 잉여속성검사(Excess Property Checks)

1. 핵심개념

  • 객체 리터럴을 변수에 바로 대입하거나 인자로 넘길 때, 그 타입에 정의되지 않은 속성이 포함되면 오류가 발생한다.
  • 하지만 일반 변수에 저장 후 넘기면 오류가 발생하지 않는다.
interface User {
  name: string;
  age: number;
}

const u: User = {
  name: "Alice",
  age: 30,
  email: "example@example.com"
}

 

위의 코드에서 u의 email User 타입에 없으므로 에러가 발생한다. 하지만 아래와 같은 예시처럼 잉여속성검사를 우회할 수 있다.

 

1. 구조적 타이핑 : 타입이 선언된 이름과 무관하게 속성의 구조가 같으면 호환된다고 판단하는 방식. 협업 시 유연함을 주지만, 너무 느슨할 수도 있음.

// User에는 email이 여전히 없지만 충족됨
const data = {
  name: "Alice",
  age: 30,
  email: "example@example.com"
}

const u:User = data;

 

2. 타입 단언 : 의도된 속성 외에 속성이 존재해도 컴파일러에게 타입을 알려줌으로서 선언한 타입을 덮어씌우는 것. 주로 unknown, any의 불확실한 타입을 단언하면서 사용. 오히려 타입선언으로 이것을 우회하는 것은 매우 위험한 방식임. 런타임에 타입을 바꾸는 캐스팅과는 달리 컴파일러가 오류를 잡아내지 못하게 만들 수 있어 되도록 타입추론에 맞기는게 현명함.

const u = {
  name: "Alice",
  age: 30,
  email: "example@example.com"
} as User

 

 

2. satisfies 키워드

satisfies는 추가 속성을 허용하지 않으면서도 타입을 안전하게 확인할 수 있어 더 강력한 방식

as User(타입단언)은 억지로 타입을 덮어씌우지만, satisfies User는 구조가 정확히 일치하는지 검증한다.

const user = {
  name: "Alice",
  age: 30,
  email: "alice@example.com"
} satisfies User; // ❌ 에러 발생 (email은 User에 없으므로)

// 하지만 아래처럼 email 빼면 OK:
const user2 = {
  name: "Bob",
  age: 25
} satisfies User; // ✅ 통과