Select
Sub-field selection on embedded objects — narrow return types by selecting specific object fields.
Object fields support sub-field selection in select options. You can retrieve only the specific nested fields you need, and the return type narrows accordingly.
All examples use this schema:
object Address {
street String
city String
state String
zipCode String?
}
object GeoPoint {
lat Float
lng Float
label String?
}
model User {
id Record @id
name String
address Address
shipping Address?
locations GeoPoint[]
}Boolean Selection
Passing true for an object field returns the full object with all its fields:
const user = await client.db.User.findOne({
select: { name: true, address: true },
});
// user.address: Address (full object)
// user.address.street ✓
// user.address.city ✓
// user.address.state ✓
// user.address.zipCode ✓This is identical to not specifying a select for that field — true means "include everything."
Object Sub-Field Selection
Pass an object with specific fields set to true to narrow the return type to only those fields:
const user = await client.db.User.findOne({
select: { name: true, address: { city: true, state: true } },
});
// user.address: { city: string; state: string }
// user.address.city ✓
// user.address.state ✓
// user.address.street — type error, not selectedOnly the fields you specify are included in the return type. Accessing unselected fields produces a TypeScript compile-time error.
Array of Objects
Sub-field selection works on array object fields. The narrowing applies to each element:
const user = await client.db.User.findOne({
select: { locations: { lat: true } },
});
// user.locations: { lat: number }[]
// Each element only has the `lat` fieldOptional Object Fields
When an optional object field is selected with sub-field narrowing, the | undefined is preserved:
const user = await client.db.User.findOne({
select: { shipping: { city: true } },
});
// user.shipping: { city: string } | undefinedIf the record has no shipping value (NONE), the field is undefined. If it does have a value, only the selected sub-fields are present in the type.
Select Within Include
When using select inside an include clause for related models, the select is type-level only — the runtime returns full related objects. This is a deliberate design choice since related records are fetched as complete entities.
// Schema context:
// model Post {
// id Record @id
// title String
// content String?
// authorId Record
// author Relation @field(authorId) @model(User)
// }
const posts = await client.db.Post.findMany({
include: {
author: {
select: { name: true, address: { city: true } },
},
},
});
// TypeScript type: posts[n].author has { name: string; address: { city: string } }
// Runtime: full User objects are returnedselect inside include only narrows the TypeScript type — it does not affect what data is fetched at runtime. If you need to limit data transfer, use top-level select on the model you are querying directly.
For more details on select and include behavior, see Select & Include.