Skip to content

Commit 7cf2cc2

Browse files
committed
Byte-shave typeof utils
1 parent 81cb1a8 commit 7cf2cc2

4 files changed

Lines changed: 39 additions & 20 deletions

File tree

src/core/immerClass.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ import {
2626
current,
2727
ImmerScope,
2828
registerChildFinalizationCallback,
29+
ArchType,
30+
MapSetPlugin,
31+
AnyMap,
32+
AnySet,
33+
isObjectish,
34+
isFunction,
35+
isBoolean
2936
} from "../internal"
3037

3138
interface ProducersFns {
@@ -45,11 +52,10 @@ export class Immer implements ProducersFns {
4552
useStrictShallowCopy?: StrictMode
4653
useStrictIteration?: boolean
4754
}) {
48-
if (typeof config?.autoFreeze === "boolean")
49-
this.setAutoFreeze(config!.autoFreeze)
50-
if (typeof config?.useStrictShallowCopy === "boolean")
55+
if (isBoolean(config?.autoFreeze)) this.setAutoFreeze(config!.autoFreeze)
56+
if (isBoolean(config?.useStrictShallowCopy))
5157
this.setUseStrictShallowCopy(config!.useStrictShallowCopy)
52-
if (typeof config?.useStrictIteration === "boolean")
58+
if (isBoolean(config?.useStrictIteration))
5359
this.setUseStrictIteration(config!.useStrictIteration)
5460
}
5561

@@ -74,7 +80,7 @@ export class Immer implements ProducersFns {
7480
*/
7581
produce: IProduce = (base: any, recipe?: any, patchListener?: any) => {
7682
// curried invocation
77-
if (typeof base === "function" && typeof recipe !== "function") {
83+
if (isFunction(base) && !isFunction(recipe)) {
7884
const defaultBase = recipe
7985
recipe = base
8086

@@ -88,9 +94,8 @@ export class Immer implements ProducersFns {
8894
}
8995
}
9096

91-
if (typeof recipe !== "function") die(6)
92-
if (patchListener !== undefined && typeof patchListener !== "function")
93-
die(7)
97+
if (!isFunction(recipe)) die(6)
98+
if (patchListener !== undefined && !isFunction(patchListener)) die(7)
9499

95100
let result
96101

@@ -109,7 +114,7 @@ export class Immer implements ProducersFns {
109114
}
110115
usePatchesInScope(scope, patchListener)
111116
return processResult(result, scope)
112-
} else if (!base || typeof base !== "object") {
117+
} else if (!base || !isObjectish(base)) {
113118
result = recipe(base)
114119
if (result === undefined) result = base
115120
if (result === NOTHING) result = undefined
@@ -129,7 +134,7 @@ export class Immer implements ProducersFns {
129134

130135
produceWithPatches: IProduceWithPatches = (base: any, recipe?: any): any => {
131136
// curried invocation
132-
if (typeof base === "function") {
137+
if (isFunction(base)) {
133138
return (state: any, ...args: any[]) =>
134139
this.produceWithPatches(state, (draft: any) => base(draft, ...args))
135140
}

src/plugins/patches.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ import {
2323
errors,
2424
DRAFT_STATE,
2525
getProxyDraft,
26-
ImmerScope
26+
ImmerScope,
27+
isObjectish,
28+
isFunction
2729
} from "../internal"
2830

2931
export function enablePatches() {
@@ -112,7 +114,7 @@ export function enablePatches() {
112114
for (let i = 0; i < path.length - 1; i++) {
113115
const key = path[i]
114116
current = get(current, key)
115-
if (typeof current !== "object" || current === null) {
117+
if (!isObjectish(current) || current === null) {
116118
throw new Error(`Cannot resolve path at '${path.join("/")}'`)
117119
}
118120
}
@@ -333,10 +335,9 @@ export function enablePatches() {
333335
(p === "__proto__" || p === "constructor")
334336
)
335337
die(errorOffset + 3)
336-
if (typeof base === "function" && p === "prototype")
337-
die(errorOffset + 3)
338+
if (isFunction(base) && p === "prototype") die(errorOffset + 3)
338339
base = get(base, p)
339-
if (typeof base !== "object") die(errorOffset + 2, path.join("/"))
340+
if (!isObjectish(base)) die(errorOffset + 2, path.join("/"))
340341
}
341342

342343
const type = getArchtype(base)

src/utils/common.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,14 @@ const objectCtorString = Object.prototype.constructor.toString()
3838
const cachedCtorStrings = new WeakMap()
3939
/*#__PURE__*/
4040
export function isPlainObject(value: any): boolean {
41-
if (!value || typeof value !== "object") return false
4241
const proto = Object.getPrototypeOf(value)
4342
if (proto === null || proto === Object.prototype) return true
4443

4544
const Ctor =
4645
Object.hasOwnProperty.call(proto, "constructor") && proto.constructor
4746
if (Ctor === Object) return true
4847

49-
if (typeof Ctor !== "function") return false
48+
if (!isFunction(Ctor)) return false
5049

5150
let ctorString = cachedCtorStrings.get(Ctor)
5251
if (ctorString === undefined) {
@@ -160,8 +159,20 @@ export function isSet(target: any): target is AnySet {
160159
return target instanceof Set
161160
}
162161

162+
export function isObjectish(target: any) {
163+
return typeof target === "object"
164+
}
165+
166+
export function isFunction(target: any): target is Function {
167+
return typeof target === "function"
168+
}
169+
170+
export function isBoolean(target: any): target is boolean {
171+
return typeof target === "boolean"
172+
}
173+
163174
export function getProxyDraft<T extends any>(value: T): ImmerState | null {
164-
if (typeof value !== "object") return null
175+
if (!isObjectish(value)) return null
165176
return (value as {[DRAFT_STATE]: any})?.[DRAFT_STATE]
166177
}
167178

@@ -268,6 +279,6 @@ const dontMutateMethodOverride = {
268279

269280
export function isFrozen(obj: any): boolean {
270281
// Fast path: primitives and null/undefined are always "frozen"
271-
if (obj === null || typeof obj !== "object") return true
272282
return Object.isFrozen(obj)
283+
if (obj === null || !isObjectish(obj)) return true
273284
}

src/utils/errors.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import {isFunction} from "../internal"
2+
13
export const errors =
24
process.env.NODE_ENV !== "production"
35
? [
@@ -39,7 +41,7 @@ export const errors =
3941
export function die(error: number, ...args: any[]): never {
4042
if (process.env.NODE_ENV !== "production") {
4143
const e = errors[error]
42-
const msg = typeof e === "function" ? e.apply(null, args as any) : e
44+
const msg = isFunction(e) ? e.apply(null, args as any) : e
4345
throw new Error(`[Immer] ${msg}`)
4446
}
4547
throw new Error(

0 commit comments

Comments
 (0)