[TypeScript] 오브젝트가 동일 인터페이스(interface)인지 확인하기
타입스크립트는 자바스크립트로 변환되어 동작하므로 인터페이스를 비교할 방법은 없습니다.
자바스크립트에서 사용하는 꼼수를 그대로 사용해야 한다는 뜻입니다.
0. 테스트 환경 만들기
테스트를 위해 인터페이스 2개를 아래와 같이 만듭니다.
export interface Test1Interface
{
Test1_string: string,
Test1_int: number,
}
export interface Test2Interface
{
Test2_string: string,
Test2_int: number,
}
아래와 같이 인터페이스를 가지고 있는 변수를 만듭니다.
(저는 클래스를 선호하기 때문에 클래스로 작성했습니다.)
Test1Inf: Test1Interface
= {
Test1_int: 1
, Test1_string: "Test1"
};
Test2Inf: Test2Interface
= {
Test2_int: 2
, Test2_string: "Test2"
};
Test3: any
= {
Test1_int: 1
, Test2_int: 2
};
1. 자바스크립트에서 같은 형식의 JSON 인지 확인하는 방법
들어온 오브젝트에 비교하려는 인터페이스에만 있는 특정 속성이 있는지 확인하여
해당 오브젝트가 인터페이스와 같은지를 확인해야 합니다.
/**
* 'Test1_int'와 'Test1_string'을 가지고 있으면 true를 리턴한다.
* @param obj1 체크할 오브젝트
* @returns Test1Interface를 가지고 있는지 여부
*/
InterfaceCheck1(obj1: any): boolean
{
let bReturn: boolean = false;
if ("object" === typeof obj1)
{//오브젝트 일때
//'Test1_int'와 'Test1_string'을 가지고 있는지 확인
bReturn = ('Test1_int' in obj1) && ('Test1_string' in obj1);
}
return bReturn;
}
14번 줄 : 'Test1_int'와 'Test1_string'를 가지고 있는지 확인하는 코드입니다.
수동으로 확인한다는 문제가 있지만 오브젝트가 해당 속성을 가지고 있는지 확인할 수 있습니다.
2. 오브젝트끼리 비교
타입스크립트의 인터페이스는 자바스크립트로 변환되면 사라지므로 생성된 개체를 사용해야 합니다.
(비교용으로 생성하든, 사용 중인 것을 사용하든...)
두 오브젝트를 비교하려면 한쪽의 속성을 기준으로 다른 쪽에도 해당 속성이 있는지 확인해야 합니다.
/**
* 두 오브젝트의 속성을 비교하여 같은 인터페이스를 사용하는 개체인지 판별한다.
* 정밀도는 내부의 nCheckCount변수로 설정된 값으로 최대 비교할 속성의 개수다.
* 이 값이 높을 수록 많은 속성으 비교하므로 정확성은 올라가지만 부하가 심해진다.
* 정밀도를 낮게 잡으면 obj1와 obj2의 순서만 바꿔도 다른 값이 나올 수 있는 가능성이 있다.
* @param obj1
* @param obj2
* @returns
*/
public InterfaceCheck2(obj1: any, obj2: any): boolean
{
let bReturn: boolean = false;
//비교할 오브젝트의 속성 수
let nCheckCount: number = 2;
let s1 = typeof obj1;
let s2 = typeof obj2;
if ("object" === s1 && "object" === s2)
{//둘다 오브젝트 일때
//1번 오브잭트의 속성 이름을 추출한다.
let arrObj1: string[] = Object.keys(obj1);
//체크 성공여부 임시 저장
let bCheckTemp: boolean = false;
for (let i = 0; i < nCheckCount && i < arrObj1.length; ++i)
{
let sItem = arrObj1[i];
bCheckTemp = (sItem in obj2);
if (false === bCheckTemp)
{//일치하는게 없다.
//모두 일치하지 않으면 같은 인터페이스라고 할 수 없으므로
//더 이상 비교할 필요가 없다.
break;
}
}//end for i
if (true === bCheckTemp)
{//모든 체크가 성공했다.
//같은 인터페이스를 사용하는 개체라고 판단 한다.
bReturn = true;
}
}
return bReturn;
}
24번 줄 : 원본에서 비교용으로 사용될 속성 이름을 추출합니다.
33번 줄 : 해당 속성이 비교용 오브젝트에 있는지 판단합니다.
34번 줄 : 모든 속성이 있어야 같은 인터페이스라고 판단할 수 있으므로
하나라도 일치하지 않으면 'false' 처리합니다.
44번 줄 : 모든 체크가 성공했으면 'bCheckTemp'는 'true'가 됩니다.
마무리
참고 : stackoverflow - Typescript: How to check interface type 에서 Marcel Armada-Castellon님의 답변
샘플 : github - dang-gun/HtmlJavascriptSamples/InterfaceCheckTest
API에서 넘어온 데이터같이 인터페이스를 상속받지 않고 데이터가 만들어지거나 할 때 많이 필요한 기능인데.....
아무래도 수작업하는 게 맞는 거라 따로 지원하지 않는 거겠죠?
ㅎㅎㅎ