객체(Object)

ReScript의 객체는 레코드와 비슷합니다. 하지만,

  • 타입 선언이 필요 없습니다.

  • 레코드와 달리 구조적(structural)이고 다형성적(polymorphic)입니다.

  • 객체가 JS로부터 전달된 것이 아니면 업데이트할 수 없습니다.

  • 패턴 매칭을 지원하지 않습니다.

ReScript 레코드는 깔끔한 JavaScript 객체로 컴파일될 수 있지만, 보시다시피 JS 객체를 모방하거나 바인딩할 때는 ReScript의 객체가 더 나은 후보입니다.

타입 선언

레코드와 달리 선택적입니다. 객체의 타입은 값에서 유추되므로 객체의 타입 선언을 굳이 작성할 필요가 없습니다. 그럼에도 불구하고, 타입 선언 문법을 보여드리자면 이러합니다.

ReScriptJS Output
type person = {
  "age": int,
  "name": string
};

레코드 타입의 문법처럼 보이지만 필드 이름이 따옴표로 감싸져 있습니다.

생성

다음과 같이 새로운 객체를 만들 수 있습니다.

ReScriptJS Output
let me = {
  "age": 5,
  "name": "Big ReScript"
}

참고: 위에서 언급한 바와 같이, 여기서 me는 레코드와 달리, "age""name"의 필드를 사용해 적합한 타입 선언을 찾으려고 하지 않습니다. 대신에 me 타입은 {"age": int, "name": string}로 추론됩니다. 이점은 편리하지만, 다음과 같이 의도치 않은 코드가 오류 없이 타입 검사를 통과한다는 것을 의미합니다.

ReScriptJS Output
type person = {
  "age": int
};

let me = {
  "age": "hello!" // age는 문자열(string)임에도 에러가 나지 않음
}

이는 타입 검사기가 meperson 타입을 일치시키려 하지 않기 때문입니다. 객체의 값을 미리 선언된 객체 타입으로 강제 지정하려면 다음과 같이 값에 어노테이션을 주면 됩니다.

RES
let me: person = { "age": "hello!" }

이제 타입 시스템은 정상적으로 오류를 보고할 것입니다.

접근

ReScriptJS Output
let age = me["age"]

변경

객체가 JavaScript 측에서 가져온 바인딩이 아니면 수정이 허용되지 않습니다. JS 측에서 가져온 바인딩의 경우, 다음과 같이 =를 사용합니다.

ReScriptJS Output
type student = {
  @set "age": int,
  @set "name": string,
}
@module("MyJSFile") external student1: student = "student1"

student1["name"] = "Mary"

병합 타입

하나의 객체 타입 정의를 다른 객체로 확장하고 싶다면 다음과 같이 ...을 사용하세요.

ReScriptJS Output
type point2d = {
  "x": float,
  "y": float,
}
type point3d = {
  ...point2d,
  "z": float,
}

let myPoint: point3d = {
  "x": 1.0,
  "y": 2.0,
  "z": 3.0,
}

이것은 객체 값이 아닌 객체 타입에서만 작동합니다!

사용 팁과 트릭

객체가 타입 선언이 필요하지 않는 데다 ReScript가 모든 타입을 알아서 추론해주기 때문에, 모든 JavaScript API에 매우 빠르고 쉽게 바인딩할 수 있습니다. 그러나 안전하지는 않습니다. 다음에서 JS 출력 탭을 확인하세요.

ReScriptJS Output
// The type of document is just some random type 'a
// that we won't bother to specify
@val external document: 'a = "document"

// call a method
document["addEventListener"]("mouseup", _event => {
  Js.log("clicked!")
})

// get a property
let loc = document["location"]

// set a property
document["location"]["href"] = "rescript-lang.org"

이곳에 사용된 external 기법은 뒤에서 더 자세히 다룰 예정입니다. 이것은 특정 라이브러리에 대한 바인딩이 존재하는지에 대한 걱정 없이 일부 ReScript 코드를 작성하기 시작할 수 있는 훌륭한 방법입니다.