객체 리터럴은 다른 변수에 할당할 때나 인수로 전달할 때, 초과 프로퍼티 검사를 받는다.
interface Person {
name: string;
age: number;
}
function getName(person: Person): string {
if (person.name)
return person.name;
else
return "no name";
}
const noman = {
name: "Noman",
age: 18,
favorite: "movie"
};
getName(noman);
getName({ name: "NOMAN", age: 18, favorite: "movie" }); // 에러
요구하는 인터페이스인 Person
에 명시되지 않은 프로퍼티를 갖고 있기에 에러가 발생했다.
그러나 똑같은 객체를 변수에 할당한 뒤 전달하면 에러가 발생하지 않는다.
getname({ name: "NOMAN", age: 18, favorite: "movie" } as Person);
또는 타입 단언 as
문법을 이용하여 초과 프로퍼티 검사를 피할 수 있다.
프로퍼티를 필수가 아닌 선택적으로 할당하도록 정의할 수 있다.
interface Person {
name?: string;
age?: number;
}
이 경우 name
과 age
프로퍼티는 선택적 프로퍼티가 된다. 즉, 해당 인터페이스를 이용하여 정의할 때 선택적 프로퍼티는 있어도 되고 없어도 된다.
const man = {
name: "Man",
favorite: "war"
};
const girl = {};
const noman = {
favorite: "movie"
};
getName(man);
getName(girl);
getName(noman); // 에러
getName(noman as Person);
noman
의 경우, Person
에 정의된 선택적 프로퍼티가 하나도 없으며 초과 프로퍼티 favorite
를 가지고 있다. 이때는 객체 리터럴이 아닌 변수를 전달했음에도 에러가 발생했다.
이런 방법으로 초과 프로퍼티 검사를 피하고 싶을 때는 인터페이스에 정의된 프로퍼티를 한 개 이상 가지고 있어야 한다.
그렇지 않다면 타입 단언을 사용하거나, 문자열 인덱스 서명을 이용할 수 있다.
interface Person {
name?: string;
age?: number;
[propname: string]: any; // string 타입의 index에 any 타입의 값을 할당함
}
const noman: Person = {
name: "Noman",
favorite: "movie"
};
console.log(noman["favorite"]); // "movie"
타입스크립트에서 인덱스 서명의 타입은 string
또는 number
여야 한다.
interface Person {
name?: string; // 에러
age: number; // 에러
favorite: string;
[propname: string]: string;
}
인덱스로 할당할 값의 타입이 any
가 아닌 경우, 인터페이스에 명시된 모든 프로퍼티는 모두 해당 타입을 따라야 한다. 또한, 선택적 프로퍼티 name?: string
를 사용한 경우, string | undefined
타입을 인덱스 키의 타입인 string
에 할당할 수 없다 는 에러가 발생한다.