Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions __tests__/type-external.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {isType, JSONArray, JSONObject, JSONTypes} from "type-plus"
import {Draft} from "../src/types/types-external"
import {createDraft, current, original} from "../src/immer"

describe("Draft<T>", () => {
test("can use JSONTypes as T", () => {
Expand All @@ -17,3 +18,27 @@ describe("Draft<T>", () => {
isType.equal<true, [string, number, JSONArray, JSONObject], A>()
})
})

describe("current() typings", () => {
test("returns non-draft type from a draft input", () => {
type Base = Readonly<{a: boolean}>
const base: Base = {a: true}
const draft = createDraft<Base>(base)
const result = current(draft)

// Readonly base ensures Draft<Base> differs, exposing current()'s typing.
isType.equal<true, Base, typeof result>()
})
})

describe("original() typings", () => {
test("returns non-draft type from a draft input", () => {
type Base = Readonly<{a: boolean}>
const base: Base = {a: true}
const draft = createDraft<Base>(base)
const result = original(draft)

// Readonly base ensures Draft<Base> differs, exposing original()'s typing.
isType.equal<true, Base, typeof result>()
})
})
5 changes: 3 additions & 2 deletions src/core/current.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
die,
Draft,
isDraft,
shallowCopy,
each,
Expand All @@ -11,8 +12,8 @@ import {
} from "../internal"

/** Takes a snapshot of the current state of a draft and finalizes it (but without freezing). This is a great utility to print the current state during debugging (no Proxies in the way). The output of current can also be safely leaked outside the producer. */
export function current<T>(value: T): T
export function current(value: any): any {
export function current<T>(value: Draft<T>): T
export function current(value: Draft<any>): any {
if (!isDraft(value)) die(10, value)
return currentImpl(value)
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/immerClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ export class Immer implements ProducersFns {

createDraft<T extends Objectish>(base: T): Draft<T> {
if (!isDraftable(base)) die(8)
if (isDraft(base)) base = current(base)
if (isDraft(base)) base = current(base as Draft<T>)
const scope = enterScope(this)
const proxy = createProxy(scope, base, undefined)
proxy[DRAFT_STATE].isManual_ = true
Expand Down
6 changes: 3 additions & 3 deletions src/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
DRAFT_STATE,
DRAFTABLE,
Objectish,
Drafted,
Draft,
AnyObject,
AnyMap,
AnySet,
Expand Down Expand Up @@ -66,8 +66,8 @@ export function isPlainObject(value: any): boolean {

/** Get the underlying object that is represented by the given draft */
/*#__PURE__*/
export function original<T>(value: T): T | undefined
export function original(value: Drafted<any>): any {
export function original<T>(value: Draft<T>): T
export function original(value: Draft<any>): any {
if (!isDraft(value)) die(15, value)
return value[DRAFT_STATE].base_
}
Expand Down
Loading