Skip to content

Commit

Permalink
Add TypeScript definition (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
BendingBender authored and sindresorhus committed Apr 22, 2019
1 parent 4db51b6 commit dc5bb73
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 13 deletions.
107 changes: 107 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
declare namespace mapObject {
type Mapper<
SourceObjectType extends {[key: string]: unknown},
MappedObjectKeyType extends string,
MappedObjectValueType extends unknown
> = (
sourceKey: keyof SourceObjectType,
sourceValue: SourceObjectType[keyof SourceObjectType],
source: SourceObjectType
) => [MappedObjectKeyType, MappedObjectValueType];

interface Options {
/**
Recurse nested objects and objects in arrays.
@default false
*/
deep?: boolean;

/**
Target object to map properties on to.
@default {}
*/
target?: {[key: string]: unknown};
}

interface DeepOptions extends Options {
deep: true;
}

interface TargetOptions<TargetObjectType extends {[key: string]: unknown}>
extends Options {
target: TargetObjectType;
}
}

/**
Map object keys and values into a new object.
@param source - Source object to copy properties from.
@param mapper - Mapping function.
@example
```
import mapObject = require('map-obj');
const newObject = mapObject({foo: 'bar'}, (key, value) => [value, key]);
//=> {bar: 'foo'}
```
*/
declare function mapObject<
SourceObjectType extends object,
TargetObjectType extends {[key: string]: unknown},
MappedObjectKeyType extends string,
MappedObjectValueType extends unknown = unknown
>(
source: SourceObjectType,
mapper: mapObject.Mapper<
SourceObjectType,
MappedObjectKeyType,
MappedObjectValueType
>,
options: mapObject.DeepOptions & mapObject.TargetOptions<TargetObjectType>
): TargetObjectType & {[key: string]: unknown};
declare function mapObject<
SourceObjectType extends object,
MappedObjectKeyType extends string,
MappedObjectValueType extends unknown = unknown
>(
source: SourceObjectType,
mapper: mapObject.Mapper<
SourceObjectType,
MappedObjectKeyType,
MappedObjectValueType
>,
options: mapObject.DeepOptions
): {[key: string]: unknown};
declare function mapObject<
SourceObjectType extends {[key: string]: unknown},
TargetObjectType extends {[key: string]: unknown},
MappedObjectKeyType extends string,
MappedObjectValueType extends unknown
>(
source: SourceObjectType,
mapper: mapObject.Mapper<
SourceObjectType,
MappedObjectKeyType,
MappedObjectValueType
>,
options: mapObject.TargetOptions<TargetObjectType>
): TargetObjectType & {[K in MappedObjectKeyType]: MappedObjectValueType};
declare function mapObject<
SourceObjectType extends {[key: string]: unknown},
MappedObjectKeyType extends string,
MappedObjectValueType extends unknown = unknown
>(
source: SourceObjectType,
mapper: mapObject.Mapper<
SourceObjectType,
MappedObjectKeyType,
MappedObjectValueType
>,
options?: mapObject.Options
): {[K in MappedObjectKeyType]: MappedObjectValueType};

export = mapObject;
8 changes: 5 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const isObject = x =>
!(x instanceof Error) &&
!(x instanceof Date);

module.exports = function mapObj(object, fn, options, seen) {
const mapObject = (object, fn, options, seen) => {
options = Object.assign({
deep: false,
target: {}
Expand All @@ -25,7 +25,7 @@ module.exports = function mapObj(object, fn, options, seen) {
const {target} = options;
delete options.target;

const mapArray = array => array.map(x => isObject(x) ? mapObj(x, fn, options, seen) : x);
const mapArray = array => array.map(x => isObject(x) ? mapObject(x, fn, options, seen) : x);
if (Array.isArray(object)) {
return mapArray(object);
}
Expand All @@ -38,11 +38,13 @@ module.exports = function mapObj(object, fn, options, seen) {
if (options.deep && isObject(newValue)) {
newValue = Array.isArray(newValue) ?
mapArray(newValue) :
mapObj(newValue, fn, options, seen);
mapObject(newValue, fn, options, seen);
}

target[newKey] = newValue;
}

return target;
};

module.exports = mapObject;
34 changes: 34 additions & 0 deletions index.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {expectType} from 'tsd';
import mapObject = require('.');

const options: mapObject.Options = {};

const newObject = mapObject({foo: 'bar'}, (key, value) => [value, key]);
expectType<{[x: string]: 'foo'}>(newObject);
expectType<'foo'>(newObject.bar);

const obj = mapObject({foo: 'bar'}, (key, value) => [value, key], {
target: {baz: 'baz'}
});
expectType<{baz: string} & {[x: string]: 'foo'}>(obj);
expectType<'foo'>(obj.bar);
expectType<string>(obj.baz);

const obj1 = mapObject({foo: 'bar'}, (key, value) => [value, key], {
target: {baz: 'baz'},
deep: false
});
expectType<{baz: string} & {[x: string]: 'foo'}>(obj1);
expectType<'foo'>(obj1.bar);
expectType<string>(obj1.baz);

const obj2 = mapObject({foo: 'bar'}, (key, value) => [value, key], {
deep: true
});
expectType<{[key: string]: unknown}>(obj2);
const obj3 = mapObject({foo: 'bar'}, (key, value) => [value, key], {
deep: true,
target: {bar: 'baz' as const}
});
expectType<{[key: string]: unknown}>(obj3);
expectType<'baz'>(obj3.bar);
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
"node": ">=6"
},
"scripts": {
"test": "xo && ava"
"test": "xo && ava && tsd"
},
"files": [
"index.js"
"index.js",
"index.d.ts"
],
"keywords": [
"map",
Expand All @@ -36,7 +37,8 @@
"recursive"
],
"devDependencies": {
"ava": "*",
"xo": "*"
"ava": "^1.4.1",
"tsd": "^0.7.2",
"xo": "^0.24.0"
}
}
12 changes: 6 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@ $ npm install map-obj
## Usage

```js
const mapObj = require('map-obj');
const mapObject = require('map-obj');

const newObject = mapObj({foo: 'bar'}, (key, value) => [value, key]);
const newObject = mapObject({foo: 'bar'}, (key, value) => [value, key]);
//=> {bar: 'foo'}
```


## API

### mapObj(source, mapper, [options])
### mapObject(source, mapper, [options])

#### source

Type: `Object`
Type: `object`

Source object to copy properties from.

Expand All @@ -41,7 +41,7 @@ Mapping function.

#### options

Type: `Object`
Type: `object`

##### deep

Expand All @@ -52,7 +52,7 @@ Recurse nested objects and objects in arrays.

##### target

Type: `Object`<br>
Type: `object`<br>
Default: `{}`

Target object to map properties on to.
Expand Down

0 comments on commit dc5bb73

Please sign in to comment.