feat(typescript-types): Add Get<O, P>
This commit is contained in:
@@ -46,12 +46,14 @@ The types included in this library are categorized by their purpose.
|
||||
|
||||
| Type | Description |
|
||||
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`Get<O, P>`][] | Extract the type of the item at keypath `P` in object `O`. |
|
||||
| [`KeyPaths<T, O, F>`][] | A union of all keypaths of `T` where the value does not extend `F`. Separator can be set via `O['separator']`. |
|
||||
| [`OptionalKeysOf<T>`][] | A union of all keys of `T` that are marked as optional. If `T` is a union, a union of the optional keys of all union members of `T` is returned[^optional-keys-of_remark]. |
|
||||
| [`PickAssignable<T, K>`][] | Return a mapped type with all keys of `T` that extend `K`. If no key does extend `K` an empty type is returned. |
|
||||
|
||||
[^optional-keys-of_remark]: If `T` is `any`, it returns a union of string and number 'string | number'.
|
||||
|
||||
[`Get<O, P>`]: src/get.ts
|
||||
[`KeyPaths<T, O, F>`]: src/key-paths.ts
|
||||
[`OptionalKeysOf<T>`]: src/optional-keys-of.ts
|
||||
[`PickAssignable<T, K>`]: src/pick-assignable.ts
|
||||
|
||||
25
packages/typescript-types/src/get.ts
Normal file
25
packages/typescript-types/src/get.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { If } from './if.js'
|
||||
import type { KeyPath } from './key-path.js'
|
||||
import type { KeyPaths } from './key-paths.js'
|
||||
|
||||
type FilterUndefined<T> = T extends undefined ? never : T
|
||||
type FilterNull<T> = T extends null ? never : T
|
||||
type FilterUndefinedAndNull<T> = FilterUndefined<FilterNull<T>>
|
||||
|
||||
type ExtractFromForKey<Obj, Key, Rest> = Key extends keyof Obj
|
||||
? Obj[Key] extends Record<PropertyKey, unknown>
|
||||
? GetByKeyPath<Obj[Key], Rest>
|
||||
: Obj[Key]
|
||||
: Key extends keyof FilterUndefinedAndNull<Obj>
|
||||
? FilterUndefinedAndNull<Obj>[Key] | undefined
|
||||
: undefined
|
||||
|
||||
type HasNoMoreKeys<K> = K extends [] ? true : false
|
||||
|
||||
type GetByKeyPath<Obj, Keys> = If<
|
||||
HasNoMoreKeys<Keys>,
|
||||
Obj,
|
||||
Keys extends [infer Key, ...infer Rest] ? ExtractFromForKey<Obj, Key, Rest> : never
|
||||
>
|
||||
|
||||
export type Get<O extends object, P extends KeyPaths<O>> = GetByKeyPath<O, KeyPath<P>>
|
||||
19
packages/typescript-types/test/get.tst.ts
Normal file
19
packages/typescript-types/test/get.tst.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { Get } from '@/get.js'
|
||||
import { expect } from 'tstyche'
|
||||
|
||||
interface Example1 {
|
||||
requiredKey: number
|
||||
optionalKey?: number
|
||||
unknownNonOptionalKey: unknown
|
||||
undefinedNonOptionalKey: undefined
|
||||
neverKey: never
|
||||
subkey: {
|
||||
name: string
|
||||
age: number
|
||||
}
|
||||
}
|
||||
|
||||
expect<Get<Example1, 'requiredKey'>>().type.toBe<number>()
|
||||
expect<Get<Example1, 'optionalKey'>>().type.toBe<number | undefined>()
|
||||
expect<Get<Example1, 'subkey.age'>>().type.toBe<number>()
|
||||
expect<Get<Example1, 'unknownNonOptionalKey'>>().type.toBe<unknown>()
|
||||
Reference in New Issue
Block a user