Skip to content

Arktype does not work in Expo, when Disjoint.withPrefixKey is called internally #1645

Description

@davisriedel

Report a bug

The same issue that was reported in issue #1027 and fixed in arktype version 2.1.4 for Disjoint.invert is also present in Disjoint.withPrefixKey (and not yet fixed, as of version 2.2.3). Hermes does not preserve Array subclasses through Array.prototype.map.

🔎 Search Terms

Expo, React Native, Hermes

🧩 Context

Arktype 2.2.3
Typescript 7.0.2
Expo SDK 57
React Native 0.86.2
Hermes 0.16

🧑‍💻 Repro

The issue can be reproduced with any union of two object literals whose branches are disjoint at a key. For example:

import { type } from "arktype"

// TypeError: undefined is not a function
const result = type({
      results: "Record<string, unknown>[][]",
      success: "true"
}).or({
      errors: "string[]",
      results: "Record<string, unknown>[][]",
      success: "false"
})

On Expo SDK 57 / React Native 0.86.2 / Hermes 0.16, this throws TypeError: undefined is not a function at the .or(...) call at runtime.

Suggested fix

We can use a similar fix/workaround like @dolgim suggested in #1027. I patched arktype locally with the following, and can confirm that it works:

withPrefixKey(key: PropertyKey, kind: Prop.Kind): Disjoint {
      const result = this.map(entry => ({
              ...entry,
              path: [key, ...entry.path],
              optional: entry.optional || kind === "optional"
      }))

      // Workaround for Hermes
      if (!(result instanceof Disjoint)) return new Disjoint(...result)

      return result
}

However, we might need a solution that avoids any similar issues. E.g. we could make Disjoint no longer extend Array.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

Status
To do

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions