State and Workflow Patterns
Feature Rollout Case
A rollout rule can decide which typed records receive a feature.
rollout predicate
A predicate function keeps a feature gate separate from the loop that applies it.
Feature Rollout Case
rollout.ts
Replay: real traced execution (multi-file project)
type User = {
id: number;
region: "us" | "eu";
};
function enabledFor(user: User, regionFlag: "us" | "eu"): boolean {
return user.region === regionFlag;
}
const regionFlag: "us" | "eu" = "us";
const users: User[] = [
{ id: 1, region: "us" },
{ id: 2, region: "eu" },
{ id: 3, region: "us" }
];
const enabled: number[] = [];
for (const user of users) {
if (enabledFor(user, regionFlag)) {
enabled.push(user.id);
}
}
console.log(`enabled=${enabled.join(",")}`);
type User = {
id: number;
region: "us" | "eu";
};
function enabledFor(user: User, regionFlag: "us" | "eu"): boolean {
return user.region === regionFlag;
}
const regionFlag: "us" | "eu" = "eu";
const users: User[] = [
{ id: 1, region: "us" },
{ id: 2, region: "eu" },
{ id: 3, region: "us" }
];
const enabled: number[] = [];
for (const user of users) {
if (enabledFor(user, regionFlag)) {
enabled.push(user.id);
}
}
console.log(`enabled=${enabled.join(",")}`);
regionFlag ← us, users ← [object Object],[object Object],[object Object]
7 return user.region === regionFlag;8}910const regionFlag→ us: "us" | "eu" = "us"; //@regionFlag="eu"11const users→ [object Object],[object Object],[object Object]: User[] = [12 { id: 1, region: "us" },13 { id: 2, region: "eu" },14 { id: 3, region: "us" }15];1617const enabled→ (empty): number[] = [];18for (const user of users) {function enabledFor(user: User, regionFlag: "us" | "eu"): boolean
pass 1 of 33 region: "us" | "eu";4};56function enabledFor(user[object Object]: User, regionFlagus: "us" | "eu"): boolean {7 return user.region === regionFlagus;8}All 3 passes — pass 1 is the card above pass enableduser.id1 (empty) 1 2 — — 3 1 3 if (enabledFor(user, regionFlag))
pass 1 of 217const enabled: number[] = [];18for (const user of users) {19 if (enabledFor(user[object Object], regionFlagus)) {20 enabled.push(user.id1);21 }values this step(empty)enabledif (enabledFor(user, regionFlag))
pass 2 of 217const enabled: number[] = [];18for (const user of users) {19 if (enabledFor(user[object Object], regionFlagus)) {20 enabled.push(user.id3);21 }values this step1enabledconsole.log(`enabled=${enabled.join(",")}`);
21 }22}2324console.log(`enabled=${enabled1,3.join(",")}`);outputenabled=1,3
regionFlag ← eu, users ← [object Object],[object Object],[object Object]
7 return user.region === regionFlag;8}910const regionFlag→ eu: "us" | "eu" = "eu";11const users→ [object Object],[object Object],[object Object]: User[] = [12 { id: 1, region: "us" },13 { id: 2, region: "eu" },14 { id: 3, region: "us" }15];1617const enabled→ (empty): number[] = [];18for (const user of users) {function enabledFor(user: User, regionFlag: "us" | "eu"): boolean
pass 1 of 33 region: "us" | "eu";4};56function enabledFor(user[object Object]: User, regionFlageu: "us" | "eu"): boolean {7 return user.region === regionFlageu;8}All 3 passes — pass 1 is the card above pass enableduser.id1 — — 2 (empty) 2 3 — — if (enabledFor(user, regionFlag))
17const enabled: number[] = [];18for (const user of users) {19 if (enabledFor(user[object Object], regionFlageu)) {20 enabled.push(user.id2);21 }values this step(empty)enabledconsole.log(`enabled=${enabled.join(",")}`);
21 }22}2324console.log(`enabled=${enabled2.join(",")}`);outputenabled=2