import {expectTypeOf} from 'expect-type'; import type {Get} from '../index'; type NonStrict = {strict: false}; declare const get: (object: ObjectType, path: Path) => Get; type ApiResponse = { hits: { hits: Array<{ _id: string; _source: { name: Array<{ given: string[]; family: string; }>; birthDate: string; }; }>; }; }; declare const apiResponse: ApiResponse; expectTypeOf(get(apiResponse, 'hits.hits[0]._source.name')).toEqualTypeOf>(); expectTypeOf(get(apiResponse, 'hits.hits.0._source.name')).toEqualTypeOf>(); expectTypeOf(get(apiResponse, 'hits.hits[0]._source.name[0].given[0]')).toBeString(); // TypeScript is structurally typed. It's *possible* this value exists even though it's not on the parent interface, so the type is `unknown`. expectTypeOf(get(apiResponse, 'hits.someNonsense.notTheRightPath')).toBeUnknown(); type WithDictionary = { foo: Record; baz: Record; }>; }; declare const withDictionary: WithDictionary; // Should work with const array literal (non-const array is just a `string[]` and isn't useful) expectTypeOf(get(withDictionary, ['baz', 'something', 'qux', '0', 'x'] as const)).toBeBoolean(); // Should work with dynamic keys declare const someKey: string; expectTypeOf(get(withDictionary, ['foo', someKey, 'bar'] as const)).toBeNumber(); // This interface uses a tuple type (as opposed to an array). type WithTuples = { foo: [ { bar: number; }, { baz: boolean; }, ]; }; expectTypeOf>().toBeNumber(); expectTypeOf>().toBeNumber(); expectTypeOf>().toBeBoolean(); expectTypeOf>().toBeUnknown(); expectTypeOf>().toBeUnknown(); expectTypeOf>().toBeUnknown(); type EmptyTuple = Parameters<() => {}>; expectTypeOf>().toBeUnknown(); expectTypeOf>().toBeUnknown(); expectTypeOf>().toBeUnknown(); expectTypeOf>().toEqualTypeOf<0>(); type WithNumberKeys = { foo: { 1: { bar: number; }; }; }; expectTypeOf>().toBeNumber(); expectTypeOf>().toBeNumber(); expectTypeOf>().toBeUnknown(); expectTypeOf>().toBeUnknown(); // Test `readonly`, `ReadonlyArray`, optional properties, and unions with null. type WithModifiers = { foo: ReadonlyArray<{ bar?: { readonly baz: { qux: number; }; }; abc: { def: { ghi: string; }; } | null; }>; }; expectTypeOf>().toEqualTypeOf<{qux: number} | undefined>(); expectTypeOf>().toEqualTypeOf(); // Test bracket notation expectTypeOf>().toBeNumber(); // NOTE: This would fail if `[0][0]` was converted into `00`: expectTypeOf>().toBeUnknown(); expectTypeOf>().toBeNumber(); expectTypeOf>().toBeUnknown(); expectTypeOf>>}}, 'a.b[0][0][0].id', NonStrict>>().toBeNumber(); expectTypeOf>>}}, ['a', 'b', '0', '0', '0', 'id'], NonStrict>>().toBeNumber(); // Test strict version: expectTypeOf>().toEqualTypeOf(); expectTypeOf, 'foo'>>().toEqualTypeOf(); expectTypeOf, 'a'>>().toEqualTypeOf(); expectTypeOf, '1'>>().toEqualTypeOf(); expectTypeOf>().toBeBoolean(); expectTypeOf>().toBeNumber(); expectTypeOf>().toBeString(); expectTypeOf>().toEqualTypeOf<{bar: number} | undefined>(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf();