다음과 같은 코드가 있다고 하겠습니다.
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig): { color: string; area: number } {
return {
color: config.color || "red",
area: config.width ? config.width * config.width : 20,
};
}
위의 코드를 사용하는 다음 코드는 에러입니다.
let mySquare = createSquare({ colour: "red", width: 100 });
인정할만 합니다. createSquare의 인자는 SquareConfig 타입으로, 이 타입은 color 속성을 갖고 있지 colour 속성이 아니기 때문입니다. 이를 초과 속성 검사(Excess Property Checks)라고 합니다. 그런데 다음 코드는 …
let squareOptions = { colour: "red", width: 100 };
let mySquare = createSquare(squareOptions);
에러가 아닙니다. 앞서 에러가 있던 코드는 createSquare의 인자에 바로 객체 리터널를 직접 전달하고 있지만 두번째 에러가 없는 코드에서는 일단 객체 리터럴을 먼저 변수에 할당하고 그 변수를 함수에 전달하고 있습니다. 이렇게 하면 함수의 인자 타입과 변수 사이의 구조를 비교해서 그 구조이 맞다면 통과, 구조가 맞지 않다면 에러로 처리됩니다. SquareConfig는 모든 속성에 대해 옵셔널이므로 구조가 서로 호환된다고 판단되어 에러로 처리되지 않습니다. 이를 일반적인 타입 호환성(구조적 타이핑, structural typing) 검사라고 합니다. 그런데 다음 코드는 에러입니다.
let squareOptions = { colour: "red" };
let mySquare = createSquare(squareOptions);
SquareConfig는 모든 속성에 대해 옵셔널이므로 문제가 없어야 합니다. 하지만 SquareConfig 타입은 매우 특수한 경우로 처리됩니다. SquareConfig는 모든 속성이 옵셔널입니다. 이처럼 모든 속성이 옵셔널일 경우에는 반드시 속성 중 하나라도 같은 속성이 존재해야 합니다. 이런 검사를 약한 타입 감지(Weak Type Detection)라고 합니다.
