2021-12-20
|~2 min read
|367 words
Let’s assume I have a type that’s defined in a third party library. Let’s say its shape is:
type Foo = {
id: string
results: Array<{ bar: string }>
}
How might I be able to derive the type of the array (i.e., { bar: string }
)?
I asked on StackOverflow and got two interesting solutions:
ElementsOf
The first solution takes advantage of the fact that an array is indexed by integers. Because of this, we can get Typescript to infer the type of our key like so:
type Baz = Foo["results"][number]
Now, variables of type Baz
will infer the type from Foo
:
const baz: Baz = { bar: "any string" }
const bazFail1: Baz = { bam: "unknown key" } // will fail as "Type '{ bam: string; }' is not assignable to type '{ bar: string; }'."
const bazFail2: Baz = { bar: 1 } // will fail as "Type 'number' is not assignable to type 'string'.(2322)"
This also works even if the type of array results
was not homogenous (i.e., if it was mixed).
type Foo = {
id: string
results: Array<{ bar: string } | number | string>
}
ElementsOf
Another approach is to create a utility type that can infer the type.
type ElementsOf<T extends unknown[]> = T extends ReadonlyArray<infer E>
? E
: never
What’s actually happening here?
Alex Wayne (people are so helpful on the internet!) chimed in to help explain what was going on here:
This says that if if
T
is a subtype of a readonly array, infer the member value from the array and return it. IfT
is not a read only array, then returnnever
, indicating that inferring the member type failed. Seems like a lot of effort though.
On the other hand, this approach suggests a new way of thinking about Type generation that’s more dynamic. It leverages a few infrequently (to me) used types:
ReadonlyArray
typeinfer
typeI put together an interactive Typescript playground here.
Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!