When working with types that are out of your control like API responses, GraphQL codegen, or third-party libraries, you might need the type of an element inside an array, not the array itself. TypeScript makes this easy in the simple cases, but it gets trickier when the array lives inside another type and might be optional.
Some time back, I helped a teammate with this situation. This post is a recollection of that solution. We’ll start with the obvious, run into rough edges, and end with a reusable strict-safe helper.
If we have an array property and we know it’s always there, we can use T[number] to get the element type.
interface
interfaceStore
Store{
Store.orders: {
id: string;
total: number;
}[]
orders:{
id: string
id:string;
total: number
total:number}[];
}
typeOrder=
interfaceStore
Store["orders"][number];
typeOrder={
id:string;
total:number;
}
This works because Store["orders"] is an array, and indexing an array type with number gives us the element type. In other words, this is how you ask TypeScript: “give me one of its elements.”
Simple and readable. Perfect for required array properties. But what if we want a reusable version for raw arrays?
We use readonly unknown[] instead of unknown[] because it matches both mutable and readonly arrays—TypeScript considers T[] to be assignable to readonly T[].
This works for plain arrays and tuples, but what about when the array is a property of another type?
Now we can say: “give me the element type of the orders property on Store.”
However, this breaks down with strictNullChecks enabled if the property is optional. Without strict null checks, optional properties don’t include undefined in their type, so the approach above would still work. But with strict mode (which you should be using), we hit a problem.
To improve our Step 2 solution, we need to extract only the array type from the union before indexing. But we also want to keep our utility working for raw arrays from Step 1. Here’s how we do both:
The tuple syntax [K] extends [never] is important since it prevents TypeScript from distributing the check over union types, which would break the logic.
The Extract trick: When a key is passed, Extract<T[K], readonly unknown[]>[number] does three things:
Access the property: T[K] → { id: string; total: number }[] | undefined
Extract only the array type: Extract<..., readonly unknown[]> isolates the array type from the union, discarding undefined → { id: string; total: number }[]
Get the element type: [number] → { id: string; total: number }
By extracting only the array type before indexing, we avoid the type error.
In other words, this single helper covers both raw arrays and object properties without needing two separate utilities.
Edge case note: For non-array properties, this helper returns never: