| import idx from './idx'; | ||
| interface DeepStructure { | ||
| foo?: { | ||
| bar?: { | ||
| baz?: { | ||
| arr?: Array<{ | ||
| inner?: { | ||
| item?: string; | ||
| }; | ||
| }>; | ||
| }; | ||
| }; | ||
| }; | ||
| } | ||
| let deep: DeepStructure = {} as any; | ||
| let item: string | undefined | null = idx( | ||
| deep, | ||
| _ => _.foo.bar.baz.arr[0].inner.item, | ||
| ); | ||
| let listOfDeep: DeepStructure[] = []; | ||
| item = idx(listOfDeep, _ => _[0].foo.bar.baz.arr[0].inner.item); | ||
| interface NullableStructure { | ||
| foo: { | ||
| bar: { | ||
| baz: string | null; | ||
| } | null; | ||
| } | null; | ||
| } | ||
| let nullable: NullableStructure = {} as any; | ||
| let baz: string | null | undefined = idx(nullable, _ => _.foo.bar.baz); |
+64
-4
| /** | ||
| * @param { T1 } prop - Parent Object | ||
| * @param { Function } accessor - Accessor function | ||
| * @return { T2 } | ||
| * NonUndefinedOrnNull | ||
| * Exclude undefined and null from set `A` | ||
| */ | ||
| export declare function idx<T1, T2>(prop: T1, accessor: (prop: T1) => T2): T2 | null | undefined; | ||
| type NonUndefinedOrnNull<T> = T extends (undefined | null) ? never : T; | ||
| /** | ||
| * DeepRequiredArray | ||
| * Nested array condition handler | ||
| */ | ||
| interface _DeepRequiredArray<T> | ||
| extends Array<DeepRequired<NonUndefinedOrnNull<T>>> {} | ||
| /** | ||
| * DeepRequiredObject | ||
| * Nested object condition handler | ||
| */ | ||
| type _DeepRequiredObject<T> = { | ||
| [P in keyof T]-?: DeepRequired<NonUndefinedOrnNull<T[P]>> | ||
| }; | ||
| /** | ||
| * DeepRequired | ||
| * Required that works for deeply nested structure | ||
| */ | ||
| type DeepRequired<T> = T extends any[] | ||
| ? _DeepRequiredArray<T[number]> | ||
| : T extends object ? _DeepRequiredObject<T> : T; | ||
| /** | ||
| * Traverses properties on objects and arrays. If an intermediate property is | ||
| * either null or undefined, it is instead returned. The purpose of this method | ||
| * is to simplify extracting properties from a chain of maybe-typed properties. | ||
| * | ||
| * Consider the following type: | ||
| * | ||
| * const props: { | ||
| * user?: { | ||
| * name: string, | ||
| * friends?: Array<User>, | ||
| * } | ||
| * }; | ||
| * | ||
| * Getting to the friends of my first friend would resemble: | ||
| * | ||
| * props.user && | ||
| * props.user.friends && | ||
| * props.user.friends[0] && | ||
| * props.user.friends[0].friends | ||
| * | ||
| * Instead, `idx` allows us to safely write: | ||
| * | ||
| * idx(props, _ => _.user.friends[0].friends) | ||
| * | ||
| * The second argument must be a function that returns one or more nested member | ||
| * expressions. Any other expression has undefined behavior. | ||
| * | ||
| * @param prop - Parent Object | ||
| * @param accessor - Accessor function than c | ||
| * @return the property accessed if accessor function could reach to property, | ||
| * null or undefined otherwise | ||
| */ | ||
| declare function idx<T1, T2>( | ||
| prop: T1, | ||
| accessor: (prop: DeepRequired<T1>) => T2, | ||
| ): T2 | null | undefined; | ||
| export default idx; |
+1
-1
| { | ||
| "name": "idx", | ||
| "version": "2.4.0", | ||
| "version": "2.5.0", | ||
| "description": "Utility function for traversing properties on objects and arrays.", | ||
@@ -5,0 +5,0 @@ "main": "lib/idx.js", |
+25
-9
@@ -15,3 +15,3 @@ # idx [](https://circleci.com/gh/facebookincubator/idx) | ||
| ```shell | ||
| $ npm install idx | ||
| $ npm install idx babel-plugin-idx | ||
| ``` | ||
@@ -22,5 +22,19 @@ | ||
| ```shell | ||
| $ yarn add idx | ||
| $ yarn add idx babel-plugin-idx | ||
| ``` | ||
| [Configure Babel](https://babeljs.io/docs/en/configuration) to include the | ||
| `babel-plugin-idx` Babel plugin. | ||
| ```javascript | ||
| { | ||
| plugins: [ | ||
| ["babel-plugin-idx"] | ||
| ] | ||
| } | ||
| ``` | ||
| This is necessary for `idx` to behave correctly | ||
| with minimal performance impact. | ||
| ## Usage | ||
@@ -57,5 +71,6 @@ | ||
| ## Flow Type | ||
| ## Static Typing | ||
| [Flow](https://flow.org/) understands the `idx` idiom: | ||
| [Flow](https://flow.org/) and [TypeScript](https://www.typescriptlang.org/) | ||
| understand the `idx` idiom: | ||
@@ -72,9 +87,10 @@ ```javascript | ||
| ## Babel Transform | ||
| ## Babel Plugin | ||
| The `idx` runtime function exists for the purpose of illustrating the expected | ||
| behavior and is not meant to be executed. The `idx` function is used in | ||
| conjunction with a Babel plugin that replaces it with better performing code. | ||
| behavior and is not meant to be executed. The `idx` function requires the use of | ||
| a Babel plugin that replaces it with an implementation that does not depend on | ||
| details related to browser error messages. | ||
| This babel plugin searches for requires or imports to the `idx` module and | ||
| This Babel plugin searches for requires or imports to the `idx` module and | ||
| replaces all its usages, so this code: | ||
@@ -101,3 +117,3 @@ | ||
| (note that the original `import` gets also removed). | ||
| Note that the original `import` gets also removed. | ||
@@ -104,0 +120,0 @@ It's possible to customize the name of the import/require, so code that is not |
8874
42.53%6
20%175
96.63%131
13.91%