2023. 4. 26. 15:30

타입스크립트는 자바스크립트로 변환되어 동작하므로 인터페이스를 비교할 방법은 없습니다.

자바스크립트에서 사용하는 꼼수를 그대로 사용해야 한다는 뜻입니다.

 

 

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에서 넘어온 데이터같이 인터페이스를 상속받지 않고 데이터가 만들어지거나 할 때 많이 필요한 기능인데.....

아무래도 수작업하는 게 맞는 거라 따로 지원하지 않는 거겠죠?

ㅎㅎㅎ