Skip to content

Commit fac0c61

Browse files
committed
👍 Add isInstanceOf<T>
1 parent 63ab076 commit fac0c61

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

is.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,26 @@ export function isFunction(x: unknown): x is (...args: unknown[]) => unknown {
157157
return Object.prototype.toString.call(x) === "[object Function]";
158158
}
159159

160+
/**
161+
* Return `true` if the type of `x` is instance of `ctor`.
162+
*
163+
* ```ts
164+
* import is from "./is.ts";
165+
*
166+
* const a: unknown = new Date();
167+
* if (is.InstanceOf(Date)(a)) {
168+
* // a is narrowed to Date
169+
* const _: Date = a;
170+
* }
171+
* ```
172+
*/
173+
// deno-lint-ignore no-explicit-any
174+
export function isInstanceOf<T extends new (...args: any) => unknown>(
175+
ctor: T,
176+
): Predicate<InstanceType<T>> {
177+
return (x: unknown): x is InstanceType<T> => x instanceof ctor;
178+
}
179+
160180
/**
161181
* Return `true` if the type of `x` is `null`.
162182
*/
@@ -213,6 +233,7 @@ export default {
213233
RecordOf: isRecordOf,
214234
ObjectOf: isObjectOf,
215235
Function: isFunction,
236+
InstanceOf: isInstanceOf,
216237
Null: isNull,
217238
Undefined: isUndefined,
218239
Nullish: isNullish,

is_test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import is, {
77
isArrayOf,
88
isBoolean,
99
isFunction,
10+
isInstanceOf,
1011
isNull,
1112
isNullish,
1213
isNumber,
@@ -180,6 +181,46 @@ Deno.test("isFunction", async (t) => {
180181
await testWithExamples(t, isFunction, ["function"]);
181182
});
182183

184+
Deno.test("isInstanceOf<T>", async (t) => {
185+
await t.step("returns true on T instance", () => {
186+
class Cls {}
187+
assertEquals(isInstanceOf(Cls)(new Cls()), true);
188+
assertEquals(isInstanceOf(Date)(new Date()), true);
189+
assertEquals(isInstanceOf(Promise<string>)(new Promise(() => {})), true);
190+
});
191+
await t.step("returns false on non function", () => {
192+
class Cls {}
193+
assertEquals(isInstanceOf(Cls)(new Date()), false);
194+
assertEquals(isInstanceOf(Cls)(new Promise(() => {})), false);
195+
assertEquals(isInstanceOf(Cls)(""), false);
196+
assertEquals(isInstanceOf(Cls)(0), false);
197+
assertEquals(isInstanceOf(Cls)(true), false);
198+
assertEquals(isInstanceOf(Cls)(false), false);
199+
assertEquals(isInstanceOf(Cls)([]), false);
200+
assertEquals(isInstanceOf(Cls)({}), false);
201+
assertEquals(isInstanceOf(Cls)(function () {}), false);
202+
assertEquals(isInstanceOf(Cls)(null), false);
203+
assertEquals(isInstanceOf(Cls)(undefined), false);
204+
});
205+
await t.step("returns proper type predicate", () => {
206+
class Cls {}
207+
const a: unknown = new Cls();
208+
if (isInstanceOf(Cls)(a)) {
209+
const _: Cls = a;
210+
}
211+
212+
const b: unknown = new Date();
213+
if (isInstanceOf(Date)(b)) {
214+
const _: Date = b;
215+
}
216+
217+
const c: unknown = new Promise(() => {});
218+
if (isInstanceOf(Promise)(c)) {
219+
const _: Promise<unknown> = c;
220+
}
221+
});
222+
});
223+
183224
Deno.test("isNull", async (t) => {
184225
await testWithExamples(t, isNull, ["null"]);
185226
});

0 commit comments

Comments
 (0)