Selecting fields
Select explicit fields, use FIELDS selectors, and understand the returned shape.
Select the fields you need
Start with an object API name, then select one field or a list:
import { db } from "./db";
const query = db
.selectFrom("Account")
.select("Id")
.select(["Name", "AnnualRevenue"])
.limit(25);
const accounts = await query.execute();
for (const account of accounts) {
console.log(account.Id, account.Name, account.AnnualRevenue);
}Selections accumulate. Object and field names come from your generated schema, so use Salesforce API names such as AnnualRevenue rather than display labels.
Kysoql does not expose SELECT *. Explicit fields keep payloads predictable and avoid picking up newly added org fields by accident.
Rename result properties with aliases
Use "field as alias" when you want a different JavaScript property name:
import { db } from "./db";
const query = db
.selectFrom("Account")
.select(["Id as id", "Name as name", "Owner.Name as ownerName"]);
console.log(query.compile().soql);
// SELECT Id, Name, Owner.Name FROM Account
const accounts = await query.execute();
for (const account of accounts) {
console.log(account.id, account.name, account.ownerName);
}Salesforce does not support ordinary field aliases in record queries. Kysoql requests the real fields and reshapes the returned JavaScript rows for you.
An aliased relationship path becomes a flat property such as ownerName. An unaliased parent path keeps its nested relationship shape.
Grouped queries use Salesforce's native aliases for aggregate and grouped results.
Use FIELDS() when you really want expansion
selectFields("standard" | "custom" | "all") emits Salesforce's FIELDS(...) function and expands the inferred result from your generated metadata:
import { db } from "./db";
const query = db.selectFrom("Account").selectFields("all").limit(100);
console.log(query.compile().soql);
// SELECT FIELDS(ALL) FROM Account LIMIT 100FIELDS(CUSTOM) and FIELDS(ALL) can return many fields. Salesforce requires them to be bounded. Kysoql therefore requires either a literal LIMIT of at most 200 or a direct Id filter that proves the query can return no more than 200 IDs.
import { db } from "./db";
const ids = ["001000000000001AAA", "001000000000002AAA"];
const query = db
.selectFrom("Account")
.selectFields("all")
.where("Id", "in", ids);The IDs above are placeholders. Use real Salesforce IDs when you execute the query.
Do not combine a selector with direct fields it already includes. For example, select("Id").selectFields("all") would select Id twice.
Filtered codegen schemas
An object generated with a field rule is a partial schema. Typed FIELDS() selectors are disabled for that object, including inside child subqueries.
That restriction matters because Salesforce expands FIELDS(...) on the server, not from the TypeScript declarations on your machine. Use explicit .select(...) calls for filtered objects.
Apex
Apex supports selectFields("standard"). "custom" and "all" are rejected when a query switches to the Apex builder.
What comes back?
| Selection | Inferred result |
|---|---|
| Direct field | The generated field type, including null where Salesforce metadata allows it. |
| Field alias | A flat property named by the alias. |
| Date, datetime, or time | string rather than JavaScript Date. |
| Location | { latitude: number, longitude: number } with applicable nullability. |
| Parent relationship path | A nested related object with applicable relationship nullability. |
| Child subquery | SalesforceQueryResult<Row>. Native REST completes selected child pages automatically. |
| Function alias | A property named by .as(...). |
Salesforce may also include transport metadata such as attributes. Ordinary field selections do not add every possible transport property to the inferred row type. TYPEOF is the main exception because its discriminated union uses attributes.type.
Replace an existing selection
import { db } from "./db";
const base = db.selectFrom("Account").select(["Id", "Name"]);
const idsOnly = base.clearSelect().select("Id");clearSelect() starts a fresh selection set without removing filters or ordering from the earlier builder.
Continue with filtering, relationships, or SELECT functions.