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:
ElementsOfThe 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>
}ElementsOfAnother approach is to create a utility type that can infer the type.
type ElementsOf<T extends unknown[]> = T extends ReadonlyArray<infer E>
? E
: neverWhat’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
Tis a subtype of a readonly array, infer the member value from the array and return it. IfTis 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!