source: trip-planner-front/node_modules/type-fest/ts41/get.d.ts

Last change on this file was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 4.1 KB
Line 
1import {Split} from './utilities';
2import {StringDigit} from '../source/utilities';
3
4/**
5Like the `Get` type but receives an array of strings as a path parameter.
6*/
7type GetWithPath<BaseType, Keys extends readonly string[]> =
8 Keys extends []
9 ? BaseType
10 : Keys extends [infer Head, ...infer Tail]
11 ? GetWithPath<PropertyOf<BaseType, Extract<Head, string>>, Extract<Tail, string[]>>
12 : never;
13
14/**
15Splits a dot-prop style path into a tuple comprised of the properties in the path. Handles square-bracket notation.
16
17@example
18```
19ToPath<'foo.bar.baz'>
20//=> ['foo', 'bar', 'baz']
21
22ToPath<'foo[0].bar.baz'>
23//=> ['foo', '0', 'bar', 'baz']
24```
25*/
26type ToPath<S extends string> = Split<FixPathSquareBrackets<S>, '.'>;
27
28/**
29Replaces square-bracketed dot notation with dots, for example, `foo[0].bar` -> `foo.0.bar`.
30*/
31type FixPathSquareBrackets<Path extends string> =
32 Path extends `${infer Head}[${infer Middle}]${infer Tail}`
33 ? `${Head}.${Middle}${FixPathSquareBrackets<Tail>}`
34 : Path;
35
36/**
37Returns true if `LongString` is made up out of `Substring` repeated 0 or more times.
38
39@example
40```
41ConsistsOnlyOf<'aaa', 'a'> //=> true
42ConsistsOnlyOf<'ababab', 'ab'> //=> true
43ConsistsOnlyOf<'aBa', 'a'> //=> false
44ConsistsOnlyOf<'', 'a'> //=> true
45```
46*/
47type ConsistsOnlyOf<LongString extends string, Substring extends string> =
48 LongString extends ''
49 ? true
50 : LongString extends `${Substring}${infer Tail}`
51 ? ConsistsOnlyOf<Tail, Substring>
52 : false;
53
54/**
55Convert a type which may have number keys to one with string keys, making it possible to index using strings retrieved from template types.
56
57@example
58```
59type WithNumbers = {foo: string; 0: boolean};
60type WithStrings = WithStringKeys<WithNumbers>;
61
62type WithNumbersKeys = keyof WithNumbers;
63//=> 'foo' | 0
64type WithStringsKeys = keyof WithStrings;
65//=> 'foo' | '0'
66```
67*/
68type WithStringKeys<BaseType extends Record<string | number, any>> = {
69 [Key in `${Extract<keyof BaseType, string | number>}`]: BaseType[Key]
70};
71
72/**
73Get a property of an object or array. Works when indexing arrays using number-literal-strings, for example, `PropertyOf<number[], '0'> = number`, and when indexing objects with number keys.
74
75Note:
76- Returns `unknown` if `Key` is not a property of `BaseType`, since TypeScript uses structural typing, and it cannot be guaranteed that extra properties unknown to the type system will exist at runtime.
77- Returns `undefined` from nullish values, to match the behaviour of most deep-key libraries like `lodash`, `dot-prop`, etc.
78*/
79type PropertyOf<BaseType, Key extends string> =
80 BaseType extends null | undefined
81 ? undefined
82 : Key extends keyof BaseType
83 ? BaseType[Key]
84 : BaseType extends {
85 [n: number]: infer Item;
86 length: number; // Note: This is needed to avoid being too lax with records types using number keys like `{0: string; 1: boolean}`.
87 }
88 ? (
89 ConsistsOnlyOf<Key, StringDigit> extends true
90 ? Item
91 : unknown
92 )
93 : Key extends keyof WithStringKeys<BaseType>
94 ? WithStringKeys<BaseType>[Key]
95 : unknown;
96
97// This works by first splitting the path based on `.` and `[...]` characters into a tuple of string keys. Then it recursively uses the head key to get the next property of the current object, until there are no keys left. Number keys extract the item type from arrays, or are converted to strings to extract types from tuples and dictionaries with number keys.
98/**
99Get a deeply-nested property from an object using a key path, like Lodash's `.get()` function.
100
101Use-case: Retrieve a property from deep inside an API response or some other complex object.
102
103@example
104```
105import {Get} from 'type-fest';
106import * as lodash from 'lodash';
107
108const get = <BaseType, Path extends string>(object: BaseType, path: Path): Get<BaseType, Path> =>
109 lodash.get(object, path);
110
111interface ApiResponse {
112 hits: {
113 hits: Array<{
114 _id: string
115 _source: {
116 name: Array<{
117 given: string[]
118 family: string
119 }>
120 birthDate: string
121 }
122 }>
123 }
124}
125
126const getName = (apiResponse: ApiResponse) =>
127 get(apiResponse, 'hits.hits[0]._source.name');
128 //=> Array<{given: string[]; family: string}>
129```
130*/
131export type Get<BaseType, Path extends string> = GetWithPath<BaseType, ToPath<Path>>;
Note: See TracBrowser for help on using the repository browser.