Alternative to lodash.get
that makes it typed and cool as if optional chaining proposal is there.
Means you're not only safely navigate object, but you're also getting 100% autocomplete and type-safeness 🎉
Please, be aware of how this is working, and take a look limitations below, this is good to get only primitive values not an objects! (at least without generics/castings etc, which makes no sense and you can use lodash then). You better use ts-optchain if browsers your are supporting, have Proxy support. If not, use ts-optchain
anyway but with typescript transformer or babel-plugin that you can find in their docs.
More than that, optional chaining proposal has moved to Stage 3 recently, meaning it will be in TS very soon (version 3.7.0 to be precise)
This was nice experiment, but performance limitations of try catch
and problems with type inference if object is accessed is making this thing dangerous and not as cool as I thought when I wrote it initially and started using it 😇
import get from 'ts-get'
type SomeType = {
optionalField?: string
nested?: {
dangerousAccess?: string
}
} | undefined | null
const emptyObject: SomeType = {}
const withOneOptionalField: SomeType = {
optionalField: "value",
}
get(emptyObject, it => it.optionalField, "default") // -> "default"
get(withOneOptionalField, it => it.optionalField, "default") // -> "value"
get(withOneOptionalField, it => it.nested.dangerousAccess, "default") // -> "default"
get(withOneOptionalField, it => it.unknownField, "default") // -> Type error, `unknownField` doesn't exist on type
get(withOneOptionalField, it => it.optionalField, 5) // -> Type error, third argument is not assignable to type `string`
- If your path gets
null
at the end, it will bail out todefaultValue
orundefined
. If you would like to getnull
returned anyway, just pass it as adefaultValue
- If your type field is of type
null
and onlynull
orundefined
your field will be of type{}[]
. I have no idea how to fix it 🤷♂️ PR Welcome 😇🙏
type A = {
field: null | undefined// -> {}[] inside of the callback and as return type too
}
- If you return not a primitive but an object, all its nested fields will be
Required
e.g. allundefined
andnull
will be removed.
import get from 'ts-get'
type A = {
field?: {
optional?: string | null
}
}
const input: A = {}
const res = get(input, it => it.field)
res // <== Will be inferred as { optional: string }, without null and ? (undefined) which is wrong, but seems to be impossible to infer.
You can solve this issue passing down generics implicitly
import get from 'ts-get'
type A = {
field?: {
optional?: string | null
}
}
const input: A = {}
const res = get<A, A['field']>(input, it => it.field)
res // <== Will be inferred properly