Repository: sindresorhus/is
Pull request #20 (2017-10-15 21:41:31)

Add is.asyncFunction
Added `is.asyncFunction`

---

> // TODO: Change to use `isObjectOfType` once Node.js 6 or higher is targeted

Could also leverage `Symbol.toStringTag` eventually:

```js
const isStringTag => (x, tag) => x && x[Symbol.toStringTag] === tag;

is.generatorFunction = x => isStringTag(x, 'GeneratorFunction');
 
is.asyncFunction = x => isStringTag(x, 'AsyncFunction');
```

gioragutt: ```typescript
const isStringTag => (x, tag) => x && x[Symbol.toStringTag] === tag;

is.generatorFunction = x => isStringTag(x, 'GeneratorFunction');
 
is.asyncFunction = x => isStringTag(x, 'AsyncFunction');
```

just a small comment on this, you see that you always have to get `x` as the method param, and pass it to `isStringTag`?

`isStringTag` can be written like this:

```typescript
const isStringTag = tag => x => x && x[Symbol.toStringTag] === tag;
```

and the usage would be

```typescript
is.generatorFunction = isStringTag('GeneratorFunction');
is.asyncFunction = isStringTag('AsyncFunction');
```

This is the same trick as `isObjectOfType` or `isOfType`

Patch:
diff --git a/index.js b/index.js
index 6f57809..0da91b3 100644
--- a/index.js
+++ b/index.js
@@ -85,7 +85,10 @@ is.promise = x => is.nativePromise(x) || hasPromiseAPI(x);
 is.generator = x => is.iterable(x) && is.function(x.next) && is.function(x.throw);
 
 // TODO: Change to use `isObjectOfType` once Node.js 6 or higher is targeted
-is.generatorFunction = x => is.function(x) && is.function(x.constructor) && x.constructor.name === 'GeneratorFunction';
+const isFunctionOfType = type => x => is.function(x) && is.function(x.constructor) && x.constructor.name === type;
+
+is.generatorFunction = isFunctionOfType('GeneratorFunction');
+is.asyncFunction = isFunctionOfType('AsyncFunction');
 
 is.regExp = isObjectOfType('RegExp');
 is.date = isObjectOfType('Date');
diff --git a/readme.md b/readme.md
index d2e572b..9e565fb 100644
--- a/readme.md
+++ b/readme.md
@@ -84,6 +84,18 @@ Returns `true` for any object that implements its own `.next()` and `.throw()` m
 
 ##### .generatorFunction(value)
 
+##### .asyncFunction(value)
+
+Returns `true` for any `async` function that can be called with the `await` operator. 
+
+```js
+is.asyncFunction(async () => {});
+// => true
+
+is.asyncFunction(() => {});
+// => false
+```
+
 ##### .map(value)
 ##### .set(value)
 ##### .weakMap(value)


Test patch:
diff --git a/test.js b/test.js
index 43566f5..0d62dce 100644
--- a/test.js
+++ b/test.js
@@ -68,6 +68,10 @@ const types = new Map([
 	['generatorFunction', function * () {
 		yield 4;
 	}],
+	['asyncFunction', [
+		async function () {},
+		async () => {}
+	]],
 	['map', new Map()],
 	['set', new Set()],
 	['weakMap', new WeakMap()],
@@ -172,7 +176,7 @@ test('is.array', t => {
 });
 
 test('is.function', t => {
-	testType(t, 'function', ['generatorFunction']);
+	testType(t, 'function', ['generatorFunction', 'asyncFunction']);
 });
 
 test('is.buffer', t => {
@@ -215,6 +219,12 @@ test('is.generatorFunction', t => {
 	testType(t, 'generatorFunction', ['function']);
 });
 
+if (isNode8orHigher) {
+	test('is.asyncFunction', t => {
+		testType(t, 'asyncFunction', ['function']);
+	});
+}
+
 test('is.map', t => {
 	testType(t, 'map');
 });