-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(pluck): add higher-order lettable version of pluck
- Loading branch information
Showing
3 changed files
with
57 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { Observable } from '../Observable'; | ||
import { map } from './map'; | ||
import { OperatorFunction } from '../interfaces'; | ||
|
||
/** | ||
* Maps each source value (an object) to its specified nested property. | ||
* | ||
* <span class="informal">Like {@link map}, but meant only for picking one of | ||
* the nested properties of every emitted object.</span> | ||
* | ||
* <img src="./img/pluck.png" width="100%"> | ||
* | ||
* Given a list of strings describing a path to an object property, retrieves | ||
* the value of a specified nested property from all values in the source | ||
* Observable. If a property can't be resolved, it will return `undefined` for | ||
* that value. | ||
* | ||
* @example <caption>Map every click to the tagName of the clicked target element</caption> | ||
* var clicks = Rx.Observable.fromEvent(document, 'click'); | ||
* var tagNames = clicks.pluck('target', 'tagName'); | ||
* tagNames.subscribe(x => console.log(x)); | ||
* | ||
* @see {@link map} | ||
* | ||
* @param {...string} properties The nested properties to pluck from each source | ||
* value (an object). | ||
* @return {Observable} A new Observable of property values from the source values. | ||
* @method pluck | ||
* @owner Observable | ||
*/ | ||
export function pluck<T, R>(...properties: string[]): OperatorFunction<T, R> { | ||
const length = properties.length; | ||
if (length === 0) { | ||
throw new Error('list of properties cannot be empty.'); | ||
} | ||
return (source: Observable<T>) => map(plucker(properties, length))(source as any); | ||
} | ||
|
||
function plucker(props: string[], length: number): (x: string) => any { | ||
const mapper = (x: string) => { | ||
let currentProp = x; | ||
for (let i = 0; i < length; i++) { | ||
const p = currentProp[props[i]]; | ||
if (typeof p !== 'undefined') { | ||
currentProp = p; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
return currentProp; | ||
}; | ||
|
||
return mapper; | ||
} |