TGViewer
Khraks dev Khraks dev @khraks_dev · 108 subscribers
Post #47 364
#DI как в Effect Pt3
Теперь озадачился написанием аналога Effect.gen, чтобы можно было просто делать yield* вычислений и получать более читаемый код, вот искомый результат:

const program = gen(function* () {
const randomService = yield* RandomTag;
const randomNumber = random.random();
const logger = yield* LoggerTag;
logger.log(randomNumber);
return randomNumber;
});

Для реализации понадобится 2 вещи:
1. добавим на Computation вот такой символ чтобы можно было делать yield* на объекте — в реализации будем просто return yield this — вызов .next() вернет само Computation<V, S>

interface Computation<out Value, in Services extends {} = {}> {
(services: Services): Value;
[Symbol.iterator](): Generator<Computation<Value, Services>, Value, any>;
}

Добавим конструктор из коллбека и обернем все функции, которые возвращают Computation — sync, andThan, tag и тд

const make = <Value, Services extends {} = {},>(cb: (services: Services) => Value) : Computation<Value, Services> => {
const cb_ = cb as Computation<Value, Services>;
cb_[Symbol.iterator] = function* () {
return yield computation;
};
return cb_;
}

2. И сам gen
Добавим типовые хелперы — обратите внимание Services аккумулируются через &.
Недавно узнал интересный ts-прием — чтобы скастовать что-то на уровне типов можно просто сделать Extract<Some, CastTarget>, чем и воспользовался в Computation.Services:

declare namespace Computation {
export type Any = Computation<any, any>;
export type Value<C extends Any> = ReturnType<C>;
export type Services<C extends Any> = Extract<UnionToIntersection<Parameters<C>[0]>, {}>;
}

const gen = <C extends Computation.Any, A>(
f: () => Generator<C, A, unknown>
): Computation<A, Computation.Services<C>> => {
return make((services: Computation.Services<C>) => {
const iterator = f();

let state = iterator.next();

while (!state.done) {
const computation = state.value;
const value = computation(services);
state = iterator.next(value);
}

return state.value;
});
};

Готово! Можно писать в императивном стиле.
Немного переработал tag — чтобы возвращался сразу сервис, а не кусок мапки
Песочница https://tsplay.dev/mxrP1w
www.typescriptlang.org TS Playground - An online editor for exploring TypeScript and JavaScript The Playground lets you write TypeScript or JavaScript online in a safe and sharable way.
  • 🔥 4
More from @khraks_dev
  1. Sep 10, 2026Добавил еще PR с Context.Mixin, чтобы подмешивать к классу поведение Context.Service Тепер…
  2. Sep 10, 2026Post #56
  3. Sep 7, 2026Post #55
  4. Sep 3, 2026Post #54
  5. Sep 3, 2026Итак HKT на основе TypeLambda interface TypeLambda { readonly Arg1: unknown; readonly Arg2…
  6. Aug 30, 2026# HKT Дефункционализация В TypeScript нет настоящих Higher-Kinded Types (HKT). А они приме…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →