당황스럽다. 이건 뭘까?

dante Yoon·2022년 9월 13일
7

js/ts

목록 보기
2/14
post-thumbnail

잠깐, 영상으로 보고 싶다면?

https://youtu.be/81JG1sOnkas

안녕하세요, 단테입니다.
오늘은 아주 간단하지만 재미있는 타입스크립트 주제를 가져왔습니다.

타입스크립트를 공부하신지 얼마 안된 분의 코드 리뷰를 진행한 적이 있었습니다.
object literal 형식의 타입을 선언할 때 저는 보통 Record 유틸리티 타입을 사용합니다.

type Dictionary = Record<string, any>

특정 키,벨류 값과 함께 동적타입을 허용해야 할 때는 다음과 같이 index signature를 사용하기도 합니다.

interface StringArray {
  [index: number]: string;
}
 
const myArray: StringArray = getStringArray();
const secondItem = myArray[1];
          
const secondItem: string

자바스크립트를 사용할 떄는 함수의 인자가 어떤 그룹으로 묶일 수 있거나 매우 그 수가 많거나 리엑트 props처럼 동적일 경우 Object Type (object literal 형식)으로 많이 나타냅니다.

function greet(person: { name: string; age: number }) {
  return "Hello " + person.name;
}
interface Person {
  name: string;
  age: number;
}
 
function greet(person: Person) {
  return "Hello " + person.name;
}

보통 Object 타입을 나타낼 때는 위처럼 인터페이스를 사용하거나 타입을 사용하실 겁니다.

제가 코드리뷰를 진행하신 분은 위와 같이 타입을 선언하시지 않고 object 라는 타입을 사용하셨는데요,

이 타입은 무엇일까요? 그리고 언제 사용해야 할까요?

object type

이 타입을 실제 코드를 작성하면서 보시는 경우가 많이 없는 이유는 이 타입은 object literal를 표현하는 타입이 아니라 자바스크립트의 primitive type이 아닌 나머지 타입을 표현하기 위해 존재하기 떄문입니다.

object is a type that represents the non-primitive type, i.e. anything that is not number, string, boolean, bigint, symbol, null, or undefined.

이름이 object라 {} 형식의 object literal 형식을 표현한다고 오해의 여지가 많겠습니다.

declare function create(o: object | null): void;
 
// OK
create({ prop: 0 });
create(null);
create(undefined); // with `--strictNullChecks` flag enabled, undefined is not a subtype of null
Argument of type 'undefined' is not assignable to parameter of type 'object | null'.
 
create(42);
Argument of type 'number' is not assignable to parameter of type 'object'.
create("string");
Argument of type 'string' is not assignable to parameter of type 'object'.
create(false);
Argument of type 'boolean' is not assignable to parameter of type 'object'.

그렇다면 object literal을 타입으로 표현해야 할 경우 다음처럼 Record 타입이 아닌 object를 사용해도 되지 않을까요?
아쉽게도 그렇지는 않습니다.

Record 타입의 경우 key에 대한 명확한 타입이 지정되지 않아도 마치 제너릭 타입처럼 선언한 변수에서 임의의 속성 값을 조회하는 것이 가능합니다.

let recordExample: Record<any, any>;
recordExample.foo; // works

하지만 object 타입을 사용할 경우 타입스크립트는 키를 참조하지 못합니다.

let objectExample: object;
objectExample.foo; // error: Property "foo" does not exist on type "object"

아래 타입스크립트 플레이그라운드를 통해 실험해보세요!
https://www.typescriptlang.org/play?#code/DYUwLgBAhgXBBKIDGB7ATgEwDxQHYE8AaaAgPgG4BYAKCgDoAzFFK6m0SAIzhU4CtkYVp0bNWQA

따라서 object literal 타입을 명시하고 싶을 때는 Record 유틸리티 타입을 쓰는 것이 옳습니다.

감사합니다 :)

profile
성장을 향한 작은 몸부림의 흔적들

0개의 댓글