Typescript에서 런타임에 interface 검사하기

박정기·2022년 9월 22일
1

typescript

목록 보기
1/1

Typescript에서 런타임에 interface를 검사하기 위한 함수를 작성하는 방법에 대한 글입니다.

타입스크립트는 개발하는 데 여러모로 편의성을 제공해주긴 하지만 가끔 한계를 느낄 때가 있는데 그 이유 중 하나가 런타임에는 interface라는 개념이 존재하지 않게 된다는 것이다.

객체지향을 기반으로 한 백엔드에서는 Object를 설계할 때 Class를 사용하는 경우가 많기 때문에 자바스크립트에 내장된 instanceof operator로 런타임에도 타입(엄밀히 말해서 타입이랑 완전히 동일한 개념은 아니다)을 확인할 수 있는데(이 방법도 늘 추천하는 방법은 아니다), 단순히 interface로만 타입이 지정된 Object의 경우에는 코드에서의 타입 오류는 잡아낼 수 있지만 런타임에는 검사할 방법이 따로 없다.

최근에 개발한 React 컴포넌트에는 여러 interface들의 union type으로 선언된 변수가 실제 가지는 type에 따라 다른 함수를 실행해줘야 하는 경우가 있었다.

예시)
interface A {
	foo: string;
}

interface B {
	bar: number;
}

type AB = a | b;

[...]

const [value, setValue] = useState<AB>({ foo: 'foo' });

useEffect(() => {
	if (``value is A``) {
		console.log(value.foo);
	}

    if (``value is B``) {
		console.log(value.bar);
	}
}, [value]);

[...]

이런 식의 코드에서 value is a, value is b 부분에 들어갈 함수가 따로 필요한 것이다.
어려운 코드는 아니지만 같은 상황에 사용하기 위해서 간단히 기록해놓는다.

parameter type이 AB로 확실한 경우에는 in operator를 이용해서 간단하게 아래와 같이 짤 수 있고,

const instanceOfA = (object: AB) : object is A => {
    return 'foo' in object;
};

혹은 아무 변수나 parameter로 받아서 검사하고 싶다면

const instanceOfA = (object: any) : object is A => {
	if (object === null || object === undefined) return false;
    return (
    	'foo' in object && 
        typeof (object.foo) === 'string' &&
        Object.keys(object).length === 1
	);
};

와 같이 엄밀하게 작성하는 방법도 있다. 요약하자면, (1) 각 property와 동일한 이름의 property를 가졌는지, (2) 해당 property가 정의된 것과 같은 type을 가졌는지(typeof로 검사할 수 있는 type은 몇가지 없기 때문에 경우에 따라 이 부분도 따로 함수가 필요할 수도 있다), (3) property의 총 개수가 정의된 것과 동일한지(1, 2만으로는 그외의 property를 추가로 가진 경우에 대해서는 검사가 안되므로)에 대한 검사를 하는 코드이다.
null이나 undefined의 경우에는 in operator를 사용했을 때 에러가 나기 때문에 먼저 검사해주는데, 간단하게 if (object == null) return false; 와 같이 작성해도 위 코드와 같은 역할을 한다. (나는 equal operator(==)를 쓰는 것을 안좋아해서 위와 같이 쓴다..)

조금 귀찮지만 Typescript에서 interface를 검사할 필요가 있다면 위와 같이 함수를 작성해보자~

profile
오르카스튜디오 공동창업자 겸 개발자입니다. team.orcar.kr

0개의 댓글