프로그래밍프론트엔드 개발자

TypeScript의 초과 속성 검사(Excess Property Checks) 메커니즘에 대해 설명해 주십시오. 이 메커니즘이 객체에 대해 어떻게 작동하며, 컴파일 단계에서 무엇이 검사되고, 동적 속성을 가진 객체의 유형화에서 어떤 문제가 발생할 수 있습니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

TypeScript는 초과 속성 검사(Excess Property Checking) 메커니즘을 구현하여 객체 선언의 오류에 대해 프로그래머에게 경고함으로써 추가적인 안전성을 제공합니다. 이 메커니즘은 TypeScript의 구조적 유형화가 선언되지 않은 추가 속성을 허용할 수 있기 때문에 생겼으며, 이는 API 또는 폼 작업을 할 때 프로그램 논리의 오류로 이어질 수 있습니다.

질문의 배경

초과 속성 검사는 프론트엔드 개발의 안전성을 개선하기 위해 도입되었습니다. 여기서 객체 구조는 종종 엄격한 계약 모델을 따릅니다(예: JSON으로 직렬화하기 위해). 객체가 리터럴로 생성되면 해당 객체가 특정 유형의 변수에 전달되거나 저장될 때, TS는 "초과" 검사 — 즉 예상 유형에 설명되지 않은 추가 속성을 검색합니다.

문제점

프로그래머의 오류는 객체에 오타나 불필요한 속성이 포함되어 있는 경우 발견되지 않을 수 있으며, 이러한 속성은 제대로 사용되지 않거나 비즈니스 논리에서 완전히 무시되기도 합니다. 또한, 초과 속성 검사는 예기치 않게 작동할 수 있습니다 — 예를 들어, 객체가 명시적으로 유형화되지 않거나 스프레드 연산자 또는 중간 변수로 처리되는 경우입니다.

해결책

TypeScript는 초과 속성 검사를 직접 변수나 함수의 매개변수에 할당되는 객체 리터럴에 적용합니다. 검사는 객체의 모든 속성을 확인하고 선언된 유형과 비교합니다 — 만약 추가 속성이 존재하면 컴파일 오류가 발생합니다.

interface UserProfile { name: string; age: number; } const user: UserProfile = { name: "Sam", age: 25, email: "sam@mail.com" // 오류: 추가 속성 email };

초과 검사를 우회하기 위해 예를 들어 동적 속성을 가진 객체나 부분적 유형화 객체에는 인덱스 서명이 사용되거나 중간 변수를 통해 할당합니다.

interface FlexibleUser { name: string; [prop: string]: any; // 인덱스 서명은 모든 새로운 속성을 허용합니다 } const user2: FlexibleUser = { name: "Sam", age: 25, email: "sam@mail.com" // 올바르게 작동합니다 };

주요 특징:

  • 초과 속성 검사는 명시적으로 유형화된 변수에 할당된 객체 리터럴에만 적용됩니다.
  • 인덱스 서명이나 중간 변수를 통해 검사를 우회할 수 있습니다.
  • 사소한 오타와 데이터 구조의 오류로부터 보호합니다.

속임수 질문.

추가 속성을 가진 객체를 생성하고 유형이 없는 변수에 할당한 후, 타입을 다시 지정하면 초과 속성 검사가 작동합니까?

아니요, 초과 검사는 리터럴을 직접 할당할 때만 작동합니다. 객체가 미리 생성되고 나중에만 유형이 지정되면 추가 속성은 발견되지 않습니다.

const temp = { name: "John", age: 18, foo: "bar" }; const u: UserProfile = temp; // 오류가 없습니다, foo가 무시됩니다

클래스와 클래스 인스턴스에 대한 초과 속성 검사가 작동합니까?

아니요, 클래스와 클래스 인스턴스에 대해서는 이러한 검사가 수행되지 않고, 객체 리터럴에 대해서만 적용됩니다.

TS 설정에서 전역적으로 초과 검사를 비활성화할 수 있습니까?

아니요, 비활성화를 위한 별도의 설정은 없습니다. 그러나 속성에 대해 인덱스 서명을 설정하거나 type assertion('as') 연산자를 사용하여 검사가 필요하지 않음을 명시적으로 지정할 수 있습니다.

const special: UserProfile = { name: "Max", age: 22, hobby: "js" } as UserProfile;

일반적인 오류 및 안티 패턴

  • 검사를 비활성화하기 위한 type assertion 사용(객체 구조의 오류를 놓칠 수 있습니다).
  • 정당하지 않은 인덱스 서명 사용은 유형 설명의 엄격함을 약화시킵니다.

실제 사례

부정적 사례

개발자가 사용자 폼을 위한 인터페이스를 작성하여 추가 필드에서 오류가 발생하지 않도록 [key: string]: any를 허용합니다.

장점: 동적 데이터에 대한 컴파일 오류가 발생하지 않습니다.

단점: 형태 오류나 오타가 발견되지 않아서 버그를 찾기 어려워집니다.

긍정적 사례

개발자가 엄격한 인터페이스를 설정하고 동적 데이터를 엄격한 구조로 변환하는 별도의 함수를 사용하며, 사전 유효성 검사를 수행합니다.

장점: 인터페이스가 예상 계약과 항상 일치하며, 컴파일러가 오타를 포착하고 유지 보수가 용이합니다.

단점: 동적 데이터의 검증 및 매핑을 위한 추가 코드 작성을 해야 합니다.