Repository: effector/effector
Pull request #1253 (2025-03-28 08:30:37)

Improve split type errors
This PR is similar to [this one](https://github.com/effector/effector/pull/1139) - it adds more explicit errors for split operator.

This PR solves next issues: #622, #769, #999 
I added some tests for match function inference, inline prepend calls and attach in default case.

Also i'm not sure about [narrower types edge cases](https://tsplay.dev/w2ykrW) - all highlighted cases must be an errors, but ts don't think so 🥲


Patch:
diff --git a/packages/effector/index.d.ts b/packages/effector/index.d.ts
index 022746bd..a3a4bc8a 100644
--- a/packages/effector/index.d.ts
+++ b/packages/effector/index.d.ts
@@ -798,8 +798,21 @@ export function createStore<State, SerializedState extends Json = Json>(
     domain?: Domain;
   },
 ): StoreWritable<State>
+
 export function setStoreName<State>(store: Store<State>, name: string): void
 
+type UnionToIntersection<Union> = (
+  Union extends any ? (k: Union) => void : never
+  ) extends (k: infer intersection) => void
+  ? intersection
+  : never;
+
+type GetUnionLast<Union> = UnionToIntersection<
+  Union extends any ? () => Union : never
+> extends () => infer Last
+  ? Last
+  : never;
+
 /**
  * Chooses one of the cases by given conditions. It "splits" source unit into several events, which fires when payload matches their conditions.
  * Works like pattern matching for payload values and external stores
@@ -818,133 +831,217 @@ export function split<
     : Event<S>
 } & {__: Event<S>}>
 
-type SplitType<
-  Cases extends CaseRecord,
-  Match,
-  Config,
-  Source extends Unit<any>,
-> =
-  UnitValue<Source> extends CaseTypeReader<Cases, keyof Cases>
-    ?
-      Match extends Unit<any>
-      ? Exclude<keyof Cases, '__'> extends UnitValue<Match>
-        ? Config
-        : {
-          error: 'match unit should contain case names'
-          need: Exclude<keyof Cases, '__'>
-          got: UnitValue<Match>
-        }
+type MatchConstraint<Source> =
+  Unit<any>
+  | ((p: UnitValue<Source>) => void)
+  | Record<string, ((p: UnitValue<Source>) => boolean) | Store<boolean>>;
 
-      : Match extends (p: UnitValue<Source>) => void
-        ? Exclude<keyof Cases, '__'> extends ReturnType<Match>
-          ? Config
-          : {
-            error: 'match function should return case names'
-            need: Exclude<keyof Cases, '__'>
-            got: ReturnType<Match>
-          }
-
-      : Match extends Record<string, ((p: UnitValue<Source>) => boolean) | Store<boolean>>
-        ? Exclude<keyof Cases, '__'> extends keyof Match
-          ? MatcherInferenceValidator<Cases, Match> extends Match
-            ? Config
-            : {
-              error: 'case should extends type inferred by matcher function'
-              incorrectCases: Show<MatcherInferenceIncorrectCases<Cases, Match>>
-            }
-          : {
-            error: 'match object should contain case names'
-            need: Exclude<keyof Cases, '__'>
-            got: keyof Match
-          }
-
-      : {error: 'not implemented'}
-
-  : {
-    error: 'source type should extends cases'
-    sourceType: UnitValue<Source>
-    caseType: CaseTypeReader<Cases, keyof Cases>
-  }
+type CaseRecord<Keys extends PropertyKey = string> = Partial<Record<Keys | '__', UnitTargetable<any> | RoTuple<UnitTargetable<any>>>>;
 
 /**
  * Chooses one of cases by given conditions. It "splits" source unit into several targets, which fires when payload matches their conditions.
  * Works like pattern matching for payload values and external units
  */
 export function split<
-  Cases,
+  Clock extends Unit<any> | RoTuple<Unit<any>>,
+  Source extends Unit<any>,
+  Match extends MatchConstraint<Source>,
+  Cases extends CaseRecord<InferMatchKeys<Match>>,
+>(
+  config: SplitConfig<Clock, Source, Match, Cases>
+): void;
+
+type SplitConfig<
+  Clock,
   Source,
-  Match extends (
-    | Unit<any>
-    | ((p: UnitValue<Source>) => void)
-    | Record<string, ((p: UnitValue<Source>) => boolean) | Store<boolean>>
-  ),
+  Match extends MatchConstraint<Source>,
+  Cases extends CaseRecord<InferMatchKeys<Match>>
+> = Exclude<keyof Cases, '__'> extends InferMatchKeys<Match>
+  ? TypeOfMatch<Match> extends 'record'
+    ? SplitImpl<Clock, Source, Match, Cases>
+    : TypeOfMatch<Match> extends 'unit'
+      ? SplitImpl<Clock, Source, Match, Cases>
+      : TypeOfMatch<Match> extends 'fn'
+        ? SplitImpl<Clock, Source, Match, Cases>
+        : {clock?: Clock; source: Source; match: Match; cases: Cases}
+  : {
+    clock?: Clock;
+    source: Source;
+    match: RebuildMatch<Source, Match, Cases>;
+    cases: { [K in keyof Cases as K extends InferMatchKeys<Match> | '__' ? K : never]: Cases[K] };
+  };
+
+type InferMatchKeys<Match> = Match extends Unit<infer Keys>
+  ? Keys extends PropertyKey ? Keys : never
+  : Match extends (source: any) => infer Keys
+    ? Keys extends PropertyKey ? Keys : never
+    : Match extends Record<string, ((source: any) => boolean) | Store<boolean>>
+      ? keyof Match
+      : never;
+
+type TypeOfMatch<Match> =
+  Match extends Unit<any>
+    ? 'unit'
+    : Match extends (s: any) => void
+      ? 'fn'
+      : Match extends Record<string, ((p: any) => void) | Store<boolean>>
+        ? 'record'
+        : never;
+
+type RebuildMatch<
+  Source,
+  Match,
+  Cases,
+  Keys extends PropertyKey = Exclude<keyof Cases, '__'>
+> =
+  Match extends Unit<any>
+    ? Unit<Keys>
+    : Match extends (p: UnitValue<Source>) => void
+      ? (p: UnitValue<Source>) => Keys
+      : Match extends Record<string, ((p: UnitValue<Source>) => boolean) | Store<boolean>>
+        ? { [K in Keys]: K extends keyof Match ? Match[K] : (p: UnitValue<Source>) => boolean | Store<boolean> }
+        : never;
+
+type SplitImpl<
   Clock,
->(
-  config:
-    {source: Source; match: Match; cases: Cases; clock: Clock} extends infer Config
-    ?
-      Config extends {cases: CaseRecord; match: any; source: Unit<any>; clock: Unit<any> | Array<Unit<any>>}
-        ? Source extends Unit<any>
-          ? Cases extends CaseRecord
-            ? Clock extends Unit<any> | Array<Unit<any>>
-              ? SplitType<Cases, Match, {source: Source; match: Match; cases: Cases; clock: Clock}, Source>
-              : {error: 'clock should be a unit or array of units'; got: Clock}
-            : {error: 'cases should be an object with units or arrays of units'; got: Cases}
-          : {error: 'source should be a unit'; got: Source}
-
-      : Config extends {cases: CaseRecord; match: any; source: Unit<any>}
-        ? Source extends Unit<any>
-          ? Cases extends CaseRecord
-            ? SplitType<Cases, Match, {source: Source; match: Match; cases: Cases}, Source>
-            : {error: 'cases should be an object with units or arrays of units'; got: Cases}
-          : {error: 'source should be a unit'; got: Source}
-
-      : {error: 'config should be object with fields "source", "match" and "cases"'; got: Config}
-
-    : {error: 'cannot infer config object'}
-): void
-
-type CaseRecord = Record<string,  Unit<any> | Array<Unit<any>>>
-
-type MatcherInferenceIncorrectCases<Cases, Match> = {
-  [K in Exclude<keyof Match, keyof MatcherInferenceValidator<Cases, Match>>]: {
-    caseType: CaseValue<Cases, Match, K>
-    inferredType: Match[K] extends (p: any) => p is infer R ? R : never
+  Source,
+  Match,
+  Cases
+> = MatchCasesIsAssignable<Source, Match, Cases> extends infer AssignableDict
+  ? AssignableDict extends Record<string, 'yes'>
+    ? {
+      clock?: Clock;
+      source: Source;
+      match: Match;
+      cases: Cases
+    }
+    : MatchHasInference<Source, Match> extends 'yes'
+      ? {
+        clock?: Clock;
+        source: Source;
+        match: RebuildMatchInference<Source, Match, AssignableDict>;
+        cases: Show<RebuildCases<Source, Match, Cases>>;
+      }
+      : {
+        clock?: Clock;
+        source: RebuildSource<Source, Cases>;
+        match: Match;
+        cases: Show<RebuildCases<Source, Match, Cases>>;
+      }
+  : never;
+
+type MatchValueReader<Match, K, Source> =
+  K extends keyof Match
+    ? Match[K] extends (src: any) => src is infer R
+      ? UnitValue<Source> extends R
+        ? UnitValue<Source>
+        : R
+      : UnitValue<Source>
+    : UnitValue<Source>;
+
+type MatchHasInference<Source, Match> =
+  Match extends Record<string, ((p: UnitValue<Source>) => boolean) | Store<boolean>>
+    ? 'yes' extends {
+      [K in keyof Match]: UnitValue<Source> extends MatchValueReader<Match, K, Source> ? 'no' : 'yes'
+    }[keyof Match] ? 'yes' : 'no'
+    : 'no';
+
+type MatchCasesIsAssignable<
+  Source,
+  Match,
+  Cases
+> =
+  {
+    [K in keyof Cases]: IfCaseAssignableToValue<Cases[K], MatchValueReader<Match, K, Source>>
   }
-}
 
-type MatcherInferenceValidator<Cases, Match> = {
-  [
-    K in keyof Match as
-      Match[K] extends (p: any) => p is infer R
-      ? R extends CaseValue<Cases, Match, K>
-        ? K
-        : never
-      : K
-  ]: Match[K]
-}
+type IfValidCaseValue<CaseValue, MatchValue, Y, N> =
+  WhichType<CaseValue> extends 'void' | 'unknown'
+    ? Y
+    : IfAssignable<MatchValue, CaseValue, Y, N>;
+
+type IfCaseAssignableToValue<Case, Value> =
+  Case extends UnitTargetable<any>
+    ? IfValidCaseValue<UnitValue<Case>, Value, 'yes', ['no', UnitValue<Case>]>
+    : Case extends RoTuple<UnitTargetable<any>>
+      ? IsCaseAssignableToValueLoop<Case, Value>
+      : never;
+
+type IsCaseAssignableToValueLoop<Cases extends RoTuple<Unit<any>>, Value> =
+  Cases extends readonly [infer Case, ...infer Rest]
+    ? Rest extends readonly any[]
+      ? IfValidCaseValue<UnitValue<Case>, Value, 'yes', 'no'> extends 'yes'
+        ? IsCaseAssignableToValueLoop<Rest, Value>
+        : ['no', UnitValue<Case>]
+      : never
+    : 'yes';
 
-type CaseTypeReader<Cases, K extends keyof Cases> =
-  Cases[K] extends infer S
-  ? WhichType<
-    UnitValue<
-      S extends Array<any>
-      ? S[number]
-      : S
-    >
-  > extends 'void'
-    ? unknown
-    : UnitValue<
-      S extends Array<any>
-      ? S[number]
-      : S
-    >
-  : never
+type RebuildMatchInference<
+  Source,
+  Match,
+  AssignableDict
+> = Match extends Record<string, ((p: UnitValue<Source>) => boolean) | Store<boolean>>
+  ? {
+    [K in keyof Match]: K extends keyof AssignableDict
+      ? AssignableDict[K] extends ['no', infer Value]
+        ? Value extends UnitValue<Source>
+          ? (source: UnitValue<Source>) => source is Value
+          : never
+        : Match[K]
+      : Match[K]
+  }
+  : never;
 
-type CaseValue<Cases, Match, K extends keyof Match> =
-  K extends keyof Cases
-  ? CaseTypeReader<Cases, K>
-  : never
+type RebuildCases<Source, Match, Cases> = {
+  [K in keyof Cases]: K extends InferMatchKeys<Match> | '__'
+    ? RebuildCase<MatchValueReader<Match, K, Source>, Cases[K]>
+    : Cases[K];
+}
+
+type RebuildCase<MatchValue, Case> = Case extends UnitTargetable<infer CaseValue>
+  ? IfValidCaseValue<CaseValue, MatchValue, Case, UnitTargetable<MatchValue>>
+  : Case extends RoTuple<UnitTargetable<any>>
+    ? RebuildCaseLoop<Case, MatchValue>
+    : never;
+
+type RebuildCaseLoop<Cases extends readonly any[], Value, Result extends readonly any[] = []> =
+  Cases extends readonly [infer Case, ...infer Rest]
+    ? Rest extends readonly any[]
+      ? RebuildCaseLoop<
+        Rest,
+        Value,
+        [
+          ...Result,
+          IfValidCaseValue<UnitValue<Case>, Value, Case, UnitTargetable<Value>>
+        ]
+      >
+      : Result
+    : Result;
+
+type RebuildSource<Source, Cases> =
+  { [K in keyof Cases]: GetFirstUnassignableCase<UnitValue<Source>, Cases[K]> } extends infer Values
+    ? Values extends Record<string, never>
+      ? Source
+      : { [K in keyof Values as [Values[K]] extends [never] ? never : K]: Values[K] } extends infer InvalidValues
+        ? Unit<GetUnionLast<InvalidValues[keyof InvalidValues]>>
+        : never
+    : never;
+
+type GetFirstUnassignableCase<SourceValue, Case> =
+  Case extends UnitTargetable<infer CaseValue>
+    ? IfValidCaseValue<CaseValue, SourceValue, SourceValue, CaseValue>
+    : Case extends RoTuple<UnitTargetable<any>>
+      ? GetFirstUnassignableLoop<Case, SourceValue>
+      : never;
+
+type GetFirstUnassignableLoop<Cases extends RoTuple<Unit<any>>, Value> =
+  Cases extends readonly [infer Case, ...infer Rest]
+    ? Rest extends readonly any[]
+      ? IfValidCaseValue<UnitValue<Case>, Value, 'yes', 'no'> extends 'yes'
+        ? GetFirstUnassignableLoop<Rest, Value>
+        : UnitValue<Case>
+      : never
+    : never;
 
 /**
  * Shorthand for creating events attached to store by providing object with reducers for them


Test patch:
diff --git a/src/types/__tests__/effector/split.test.ts b/src/types/__tests__/effector/split.test.ts
index 100fc39c..6f071e9a 100644
--- a/src/types/__tests__/effector/split.test.ts
+++ b/src/types/__tests__/effector/split.test.ts
@@ -2,6 +2,7 @@
 import {
   createEvent,
   createStore,
+  createEffect,
   Event,
   guard,
   split,
@@ -92,18 +93,23 @@ test('case store case mismatch (should fail)', () => {
   const secondTarget: EventCallable<number> = createEvent()
   const defaultarget: EventCallable<number> = createEvent()
   split({
-    //@ts-expect-error
     source,
+    //@ts-expect-error
     match: caseStore,
     cases: {
       a: firstTarget,
+      //@ts-expect-error
       b: secondTarget,
       __: defaultarget,
     },
   })
   expect(typecheck).toMatchInlineSnapshot(`
     "
-    Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match unit should contain case names\\"; need: \\"a\\" | \\"b\\"; got: \\"a\\" | \\"c\\"; }'.
+    Type 'StoreWritable<\\"a\\" | \\"c\\">' is not assignable to type 'Unit<\\"a\\" | \\"b\\">'.
+      Types of property '__' are incompatible.
+        Type '\\"a\\" | \\"c\\"' is not assignable to type '\\"a\\" | \\"b\\"'.
+          Type '\\"c\\"' is not assignable to type '\\"a\\" | \\"b\\"'.
+    Object literal may only specify known properties, and 'b' does not exist in type '{ a: EventCallable<number>; __: EventCallable<number>; }'.
     "
   `)
 })
@@ -135,18 +141,21 @@ test('case function case mismatch (should fail)', () => {
   const secondTarget: EventCallable<number> = createEvent()
   const defaultarget: EventCallable<number> = createEvent()
   split({
-    //@ts-expect-error
     source,
+    //@ts-expect-error
     match: x => (x > 0 ? 'a' : 'c'),
     cases: {
       a: firstTarget,
+      //@ts-expect-error
       b: secondTarget,
       __: defaultarget,
     },
   })
   expect(typecheck).toMatchInlineSnapshot(`
     "
-    Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match function should return case names\\"; need: \\"a\\" | \\"b\\"; got: \\"a\\" | \\"c\\"; }'.
+    Type '\\"a\\" | \\"c\\"' is not assignable to type '\\"a\\" | \\"b\\"'.
+      Type '\\"c\\"' is not assignable to type '\\"a\\" | \\"b\\"'.
+    Object literal may only specify known properties, and 'b' does not exist in type '{ a: EventCallable<number>; __: EventCallable<number>; }'.
     "
   `)
 })
@@ -236,12 +245,14 @@ describe('any to void', () => {
       source,
       match: $case,
       cases: {
+        //@ts-expect-error
         a: [aNonVoid, aVoid],
       },
     })
     expect(typecheck).toMatchInlineSnapshot(`
       "
-      Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: number; caseType: string | void; }'.
+      Type 'EventCallable<number>' is not assignable to type 'Unit<string>'.
+      Type 'EventCallable<string>' is not assignable to type 'UnitTargetable<number>'.
       "
     `)
   })
@@ -375,13 +386,14 @@ describe('matcher function with inference', () => {
     const defTrigger = createEvent<{tag: 'a'} | B>()
     const $cFlag = createStore(false)
     split({
-      //@ts-expect-error
       source,
       match: {
+        //@ts-expect-error
         a: (src): src is B => src.tag === 'b',
         c: $cFlag,
       },
       cases: {
+        //@ts-expect-error
         a: [aFull, aPart],
         c,
         __: defTrigger,
@@ -389,7 +401,67 @@ describe('matcher function with inference', () => {
     })
     expect(typecheck).toMatchInlineSnapshot(`
       "
-      Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"case should extends type inferred by matcher function\\"; incorrectCases: { a: { caseType: A | { value: 0; }; inferredType: B; }; }; }'.
+      Type '(src: A | B) => src is B' is not assignable to type '(source: A | B) => source is A'.
+        Type predicate 'src is B' is not assignable to 'source is A'.
+          Type 'B' is not assignable to type 'A'.
+            Types of property 'tag' are incompatible.
+              Type '\\"b\\"' is not assignable to type '\\"a\\"'.
+      Type 'EventCallable<A>' is not assignable to type 'UnitTargetable<B>'.
+        The types of '__.tag' are incompatible between these types.
+          Type '\\"a\\"' is not assignable to type '\\"b\\"'.
+      Type 'EventCallable<{ value: 0; }>' is not assignable to type 'UnitTargetable<B>'.
+        Types of property '__' are incompatible.
+          Property 'tag' is missing in type '{ value: 0; }' but required in type 'B'.
+      "
+    `)
+  })
+  test('wrong inference (should fail)', () => {
+    type A = {tag: 'a'; value: 0}
+    type B = {tag: 'b'; value: 'b'}
+    const source = createEvent<A | B>()
+    const aFull = createEvent<A>()
+    const c = createEvent<A | B>()
+
+    split({
+      source,
+      match: {
+        // @ts-expect-error
+        a: (src): src is B => src.tag === 'b',
+      },
+      cases: {
+        // @ts-expect-error
+        a: [aFull, c],
+      },
+    })
+    expect(typecheck).toMatchInlineSnapshot(`
+      "
+      Type '(src: A | B) => src is B' is not assignable to type '(source: A | B) => source is A'.
+        Type predicate 'src is B' is not assignable to 'source is A'.
+          Type 'B' is not assignable to type 'A'.
+            Types of property 'tag' are incompatible.
+              Type '\\"b\\"' is not assignable to type '\\"a\\"'.
+      Type 'EventCallable<A>' is not assignable to type 'UnitTargetable<B>'.
+        The types of '__.tag' are incompatible between these types.
+          Type '\\"a\\"' is not assignable to type '\\"b\\"'.
+      "
+    `)
+  })
+  test('nullable source + type guard in case (should pass)', () => {
+    const $src = createStore<string | null>(null)
+    const a = createEvent<string>()
+
+    split({
+      source: $src,
+      match: {
+        a: (str): str is string => str !== null,
+      },
+      cases: {
+        a,
+      },
+    })
+    expect(typecheck).toMatchInlineSnapshot(`
+      "
+      no errors
       "
     `)
   })
@@ -487,17 +559,17 @@ describe('array cases', () => {
       const a = createEvent<{foo: 1}>()
       const b = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
         match: $case,
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match unit should contain case names\\"; need: \\"a\\" | \\"b\\"; got: \\"a\\"; }'.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; }'.
         "
       `)
     })
@@ -549,18 +621,18 @@ describe('array cases', () => {
       const b = createEvent<{foo: 1}>()
       const c = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
         match: $case,
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match unit should contain case names\\"; need: \\"a\\" | \\"b\\" | \\"c\\"; got: \\"a\\" | \\"b\\"; }'.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; b: EventCallable<{ foo: 1; }>; }'.
         "
       `)
     })
@@ -609,17 +681,17 @@ describe('array cases', () => {
       const a = createEvent<{foo: 1}>()
       const b = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
         match: $case,
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match unit should contain case names\\"; need: \\"a\\" | \\"b\\"; got: \\"a\\"; }'.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; }'.
         "
       `)
     })
@@ -671,18 +743,18 @@ describe('array cases', () => {
       const b = createEvent<{foo: 1}>()
       const c = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
         match: $case,
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match unit should contain case names\\"; need: \\"a\\" | \\"b\\" | \\"c\\"; got: \\"a\\" | \\"b\\"; }'.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; b: EventCallable<{ foo: 1; }>; }'.
         "
       `)
     })
@@ -705,7 +777,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: string; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: string; }'.
         "
       `)
     })
@@ -723,7 +797,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; }; }'.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: number; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: number; }'.
         "
       `)
     })
@@ -733,17 +809,17 @@ describe('array cases', () => {
       const a = createEvent<{foo: 1; bar: number}>()
       const b = createEvent<{foo: 1; bar: string}>()
       split({
-        //@ts-expect-error
         source,
         match: $case,
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 1; bar: number; }>]; }'.
         "
       `)
     })
@@ -766,7 +842,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: string; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: string; }'.
         "
       `)
     })
@@ -786,7 +864,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: string; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: string; }'.
         "
       `)
     })
@@ -797,18 +877,18 @@ describe('array cases', () => {
       const b = createEvent<{foo: 1; bar: string}>()
       const c = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
         match: $case,
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match unit should contain case names\\"; need: \\"a\\" | \\"b\\" | \\"c\\"; got: \\"a\\" | \\"b\\"; }'.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 1; bar: number; }>]; b: EventCallable<{ foo: 1; bar: string; }>; }'.
         "
       `)
     })
@@ -825,13 +905,23 @@ describe('array cases', () => {
         source,
         match: $case,
         cases: {
+          //@ts-expect-error
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -844,12 +934,18 @@ describe('array cases', () => {
         source,
         match: $case,
         cases: {
+          //@ts-expect-error
           a: [a],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; }; }'.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -859,17 +955,17 @@ describe('array cases', () => {
       const a = createEvent<{foo: 2}>()
       const b = createEvent<{foo: 2}>()
       split({
-        //@ts-expect-error
         source,
         match: $case,
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 2; }>]; }'.
         "
       `)
     })
@@ -886,13 +982,23 @@ describe('array cases', () => {
         source,
         match: $case,
         cases: {
+          //@ts-expect-error
           a: [a],
+          //@ts-expect-error
           b,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -906,13 +1012,23 @@ describe('array cases', () => {
         source,
         match: $case,
         cases: {
+          //@ts-expect-error
           a: [a],
+          //@ts-expect-error
           b,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -923,18 +1039,18 @@ describe('array cases', () => {
       const b = createEvent<{foo: 2}>()
       const c = createEvent<{foo: 2}>()
       split({
-        //@ts-expect-error
         source,
         match: $case,
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; } | { foo: 2; }; }'.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 2; }>]; b: EventCallable<{ foo: 2; }>; }'.
         "
       `)
     })
@@ -981,17 +1097,17 @@ describe('array cases', () => {
       const a = createEvent<{foo: 1}>()
       const b = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
         match: (src): 'a' => 'a',
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match function should return case names\\"; need: \\"a\\" | \\"b\\"; got: \\"a\\"; }'.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; }'.
         "
       `)
     })
@@ -1040,18 +1156,18 @@ describe('array cases', () => {
       const b = createEvent<{foo: 1}>()
       const c = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
         match: (src): 'a' | 'b' => 'a',
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match function should return case names\\"; need: \\"a\\" | \\"b\\" | \\"c\\"; got: \\"a\\" | \\"b\\"; }'.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; b: EventCallable<{ foo: 1; }>; }'.
         "
       `)
     })
@@ -1097,17 +1213,17 @@ describe('array cases', () => {
       const a = createEvent<{foo: 1}>()
       const b = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
         match: (src): 'a' => 'a',
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match function should return case names\\"; need: \\"a\\" | \\"b\\"; got: \\"a\\"; }'.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; }'.
         "
       `)
     })
@@ -1156,18 +1272,18 @@ describe('array cases', () => {
       const b = createEvent<{foo: 1}>()
       const c = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
         match: (src): 'a' | 'b' => 'a',
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match function should return case names\\"; need: \\"a\\" | \\"b\\" | \\"c\\"; got: \\"a\\" | \\"b\\"; }'.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; b: EventCallable<{ foo: 1; }>; }'.
         "
       `)
     })
@@ -1181,7 +1297,6 @@ describe('array cases', () => {
       split({
         //@ts-expect-error
         source,
-        //@ts-expect-error src is any
         match: (src): 'a' | 'b' => 'a',
         cases: {
           a: [a],
@@ -1190,8 +1305,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: string; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: string; }'.
         "
       `)
     })
@@ -1201,7 +1317,6 @@ describe('array cases', () => {
       split({
         //@ts-expect-error
         source,
-        //@ts-expect-error src is any
         match: (src): 'a' | 'b' => 'a',
         cases: {
           a: [a],
@@ -1209,8 +1324,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: number; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: number; }'.
         "
       `)
     })
@@ -1219,19 +1335,17 @@ describe('array cases', () => {
       const a = createEvent<{foo: 1; bar: number}>()
       const b = createEvent<{foo: 1; bar: string}>()
       split({
-        //@ts-expect-error
         source,
-        //@ts-expect-error src is any
         match: (src): 'a' => 'a',
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 1; bar: number; }>]; }'.
         "
       `)
     })
@@ -1250,7 +1364,6 @@ describe('array cases', () => {
         //@ts-expect-error
         source,
         match: {
-          //@ts-expect-error src is any
           write: src => src.a !== null && src.b !== null,
         },
         cases,
@@ -1258,8 +1371,10 @@ describe('array cases', () => {
 
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { a: number | null; b: number | null; }; caseType: { a: number; b: number; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'Event<{ a: number | null; b: number | null; }>' is not assignable to type 'Unit<{ a: number; b: number; }>'.
+          The types of '__.a' are incompatible between these types.
+            Type 'number | null' is not assignable to type 'number'.
+              Type 'null' is not assignable to type 'number'.
         "
       `)
     })
@@ -1273,7 +1388,6 @@ describe('array cases', () => {
       split({
         //@ts-expect-error
         source,
-        //@ts-expect-error src is any
         match: (src): 'a' | 'b' => 'a',
         cases: {
           a: [a],
@@ -1282,8 +1396,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: string; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: string; }'.
         "
       `)
     })
@@ -1294,7 +1409,6 @@ describe('array cases', () => {
       split({
         //@ts-expect-error
         source,
-        //@ts-expect-error src is any
         match: (src): 'a' | 'b' | 'c' => 'a',
         cases: {
           a: [a],
@@ -1303,8 +1417,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: string; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: string; }'.
         "
       `)
     })
@@ -1314,18 +1429,18 @@ describe('array cases', () => {
       const b = createEvent<{foo: 1; bar: string}>()
       const c = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
         match: (src): 'a' | 'b' => 'a',
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match function should return case names\\"; need: \\"a\\" | \\"b\\" | \\"c\\"; got: \\"a\\" | \\"b\\"; }'.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 1; bar: number; }>]; b: EventCallable<{ foo: 1; bar: string; }>; }'.
         "
       `)
     })
@@ -1339,17 +1454,25 @@ describe('array cases', () => {
       split({
         //@ts-expect-error
         source,
-        //@ts-expect-error src is any
         match: (src): 'a' | 'b' => 'a',
         cases: {
+          //@ts-expect-error
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -1359,16 +1482,20 @@ describe('array cases', () => {
       split({
         //@ts-expect-error
         source,
-        //@ts-expect-error src is any
         match: (src): 'a' | 'b' => 'a',
         cases: {
+          //@ts-expect-error
           a: [a],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -1377,19 +1504,17 @@ describe('array cases', () => {
       const a = createEvent<{foo: 2}>()
       const b = createEvent<{foo: 2}>()
       split({
-        //@ts-expect-error
         source,
-        //@ts-expect-error src is any
         match: (src): 'a' => 'a',
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 2; }>]; }'.
         "
       `)
     })
@@ -1403,17 +1528,25 @@ describe('array cases', () => {
       split({
         //@ts-expect-error
         source,
-        //@ts-expect-error src is any
         match: (src): 'a' | 'b' => 'a',
         cases: {
+          //@ts-expect-error
           a: [a],
+          //@ts-expect-error
           b,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -1424,17 +1557,25 @@ describe('array cases', () => {
       split({
         //@ts-expect-error
         source,
-        //@ts-expect-error src is any
         match: (src): 'a' | 'b' | 'c' => 'a',
         cases: {
+          //@ts-expect-error
           a: [a],
+          //@ts-expect-error
           b,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -1444,20 +1585,18 @@ describe('array cases', () => {
       const b = createEvent<{foo: 2}>()
       const c = createEvent<{foo: 2}>()
       split({
-        //@ts-expect-error
         source,
-        //@ts-expect-error src is any
         match: (src): 'a' | 'b' => 'a',
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; } | { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 2; }>]; b: EventCallable<{ foo: 2; }>; }'.
         "
       `)
     })
@@ -1510,19 +1649,21 @@ describe('array cases', () => {
       const a = createEvent<{foo: 1}>()
       const b = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
+        //@ts-expect-error
         match: {
           a: src => true,
         },
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match object should contain case names\\"; need: \\"a\\" | \\"b\\"; got: \\"a\\"; }'.
+        Property 'b' is missing in type '{ a: (src: { foo: 1; }) => true; }' but required in type '{ a: (src: { foo: 1; }) => true; b: (p: { foo: 1; }) => boolean | Store<boolean>; }'.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; }'.
         "
       `)
     })
@@ -1578,8 +1719,8 @@ describe('array cases', () => {
       const b = createEvent<{foo: 1}>()
       const c = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
+        //@ts-expect-error
         match: {
           a: src => true,
           b: src => true,
@@ -1587,12 +1728,14 @@ describe('array cases', () => {
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match object should contain case names\\"; need: \\"a\\" | \\"b\\" | \\"c\\"; got: \\"a\\" | \\"b\\"; }'.
+        Property 'c' is missing in type '{ a: (src: { foo: 1; }) => true; b: (src: { foo: 1; }) => true; }' but required in type '{ a: (src: { foo: 1; }) => true; b: (src: { foo: 1; }) => true; c: (p: { foo: 1; }) => boolean | Store<boolean>; }'.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; b: EventCallable<{ foo: 1; }>; }'.
         "
       `)
     })
@@ -1644,19 +1787,21 @@ describe('array cases', () => {
       const a = createEvent<{foo: 1}>()
       const b = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
+        //@ts-expect-error
         match: {
           a: src => true,
         },
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match object should contain case names\\"; need: \\"a\\" | \\"b\\"; got: \\"a\\"; }'.
+        Property 'b' is missing in type '{ a: (src: { foo: 1; bar: number; }) => true; }' but required in type '{ a: (src: { foo: 1; bar: number; }) => true; b: (p: { foo: 1; bar: number; }) => boolean | Store<boolean>; }'.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; }'.
         "
       `)
     })
@@ -1712,8 +1857,8 @@ describe('array cases', () => {
       const b = createEvent<{foo: 1}>()
       const c = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
+        //@ts-expect-error
         match: {
           a: src => true,
           b: src => true,
@@ -1721,12 +1866,14 @@ describe('array cases', () => {
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match object should contain case names\\"; need: \\"a\\" | \\"b\\" | \\"c\\"; got: \\"a\\" | \\"b\\"; }'.
+        Property 'c' is missing in type '{ a: (src: { foo: 1; bar: number; }) => true; b: (src: { foo: 1; bar: number; }) => true; }' but required in type '{ a: (src: { foo: 1; bar: number; }) => true; b: (src: { foo: 1; bar: number; }) => true; c: (p: { foo: 1; bar: number; }) => boolean | Store<boolean>; }'.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 1; }>]; b: EventCallable<{ foo: 1; }>; }'.
         "
       `)
     })
@@ -1741,9 +1888,7 @@ describe('array cases', () => {
         //@ts-expect-error
         source,
         match: {
-          //@ts-expect-error src is any
           a: src => true,
-          //@ts-expect-error src is any
           b: src => true,
         },
         cases: {
@@ -1753,9 +1898,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: string; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: string; }'.
         "
       `)
     })
@@ -1766,9 +1911,7 @@ describe('array cases', () => {
         //@ts-expect-error
         source,
         match: {
-          //@ts-expect-error src is any
           a: src => true,
-          //@ts-expect-error src is any
           b: src => true,
         },
         cases: {
@@ -1777,9 +1920,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: number; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: number; }'.
         "
       `)
     })
@@ -1788,21 +1931,21 @@ describe('array cases', () => {
       const a = createEvent<{foo: 1; bar: number}>()
       const b = createEvent<{foo: 1; bar: string}>()
       split({
-        //@ts-expect-error
         source,
+        //@ts-expect-error
         match: {
-          //@ts-expect-error src is any
           a: src => true,
         },
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Property 'b' is missing in type '{ a: (src: { foo: 1; }) => true; }' but required in type '{ a: (src: { foo: 1; }) => true; b: (p: { foo: 1; }) => boolean | Store<boolean>; }'.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 1; bar: number; }>]; }'.
         "
       `)
     })
@@ -1817,9 +1960,7 @@ describe('array cases', () => {
         //@ts-expect-error
         source,
         match: {
-          //@ts-expect-error src is any
           a: src => true,
-          //@ts-expect-error src is any
           b: src => true,
         },
         cases: {
@@ -1829,9 +1970,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: string; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: string; }'.
         "
       `)
     })
@@ -1843,11 +1984,8 @@ describe('array cases', () => {
         //@ts-expect-error
         source,
         match: {
-          //@ts-expect-error src is any
           a: src => true,
-          //@ts-expect-error src is any
           b: src => true,
-          //@ts-expect-error src is any
           c: src => true,
         },
         cases: {
@@ -1857,10 +1995,9 @@ describe('array cases', () => {
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 1; bar: number; } | { foo: 1; bar: string; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
-        Parameter 'src' implicitly has an 'any' type.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 1; bar: string; }>'.
+          Types of property '__' are incompatible.
+            Property 'bar' is missing in type '{ foo: 1; }' but required in type '{ foo: 1; bar: string; }'.
         "
       `)
     })
@@ -1870,8 +2007,8 @@ describe('array cases', () => {
       const b = createEvent<{foo: 1; bar: string}>()
       const c = createEvent<{foo: 1}>()
       split({
-        //@ts-expect-error
         source,
+        //@ts-expect-error
         match: {
           a: src => true,
           b: src => true,
@@ -1879,12 +2016,14 @@ describe('array cases', () => {
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match object should contain case names\\"; need: \\"a\\" | \\"b\\" | \\"c\\"; got: \\"a\\" | \\"b\\"; }'.
+        Property 'c' is missing in type '{ a: (src: { foo: 1; }) => true; b: (src: { foo: 1; }) => true; }' but required in type '{ a: (src: { foo: 1; }) => true; b: (src: { foo: 1; }) => true; c: (p: { foo: 1; }) => boolean | Store<boolean>; }'.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 1; bar: number; }>]; b: EventCallable<{ foo: 1; bar: string; }>; }'.
         "
       `)
     })
@@ -1899,21 +2038,27 @@ describe('array cases', () => {
         //@ts-expect-error
         source,
         match: {
-          //@ts-expect-error src is any
           a: src => true,
-          //@ts-expect-error src is any
           b: src => true,
         },
         cases: {
+          //@ts-expect-error
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -1924,20 +2069,22 @@ describe('array cases', () => {
         //@ts-expect-error
         source,
         match: {
-          //@ts-expect-error src is any
           a: src => true,
-          //@ts-expect-error src is any
           b: src => true,
         },
         cases: {
+          //@ts-expect-error
           a: [a],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -1946,21 +2093,21 @@ describe('array cases', () => {
       const a = createEvent<{foo: 2}>()
       const b = createEvent<{foo: 2}>()
       split({
-        //@ts-expect-error
         source,
+        //@ts-expect-error
         match: {
-          //@ts-expect-error src is any
           a: src => true,
         },
         cases: {
           a: [a],
+          //@ts-expect-error
           b: [b],
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
+        Property 'b' is missing in type '{ a: (src: { foo: 1; }) => true; }' but required in type '{ a: (src: { foo: 1; }) => true; b: (p: { foo: 1; }) => boolean | Store<boolean>; }'.
+        Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<{ foo: 2; }>]; }'.
         "
       `)
     })
@@ -1975,21 +2122,27 @@ describe('array cases', () => {
         //@ts-expect-error
         source,
         match: {
-          //@ts-expect-error src is any
           a: src => true,
-          //@ts-expect-error src is any
           b: src => true,
         },
         cases: {
+          //@ts-expect-error
           a: [a],
+          //@ts-expect-error
           b,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -2001,24 +2154,28 @@ describe('array cases', () => {
         //@ts-expect-error
         source,
         match: {
-          //@ts-expect-error src is any
           a: src => true,
-          //@ts-expect-error src is any
           b: src => true,
-          //@ts-expect-error src is any
           c: src => true,
         },
         cases: {
+          //@ts-expect-error
           a: [a],
+          //@ts-expect-error
           b,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
-        Parameter 'src' implicitly has an 'any' type.
-        Parameter 'src' implicitly has an 'any' type.
+        Type 'EventCallable<{ foo: 1; }>' is not assignable to type 'Unit<{ foo: 2; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '1' is not assignable to type '2'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
+        Type 'EventCallable<{ foo: 2; }>' is not assignable to type 'UnitTargetable<{ foo: 1; }>'.
+          The types of '__.foo' are incompatible between these types.
+            Type '2' is not assignable to type '1'.
         "
       `)
     })
@@ -2028,25 +2185,23 @@ describe('array cases', () => {
       const b = createEvent<{foo: 2}>()
       const c = createEvent<{foo: 2}>()
       split({
-        //@ts-expect-error
         source,
+        //@ts-expect-error
         match: {
-          //@ts-expect-error src is any
           a: src => true,
-          //@ts-expect-error src is any
           b: src => true,
         },
         cases: {
           a: [a],
           b,
+          //@ts-expect-error
           c,
         },
       })
       expect(typecheck).toMatchInlineSnapshot(`
         "
-        Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"source type should extends cases\\"; sourceType: { foo: 1; }; caseType: { foo: 2; } | { foo: 2; } | { foo: 2; }; }'.
-        Parameter 'src' implicitly has an 'any' type.
-        Parameter 'src' implicitly has an 'any' type.
+        Property 'c' is missing in type '{ a: (src: { foo: 1; }) => true; b: (src: { foo: 1; }) => true; }' but required in type '{ a: (src: { foo: 1; }) => true; b: (src: { foo: 1; }) => true; c: (p: { foo: 1; }) => boolean | Store<boolean>; }'.
+        Object literal may only specify known properties, and 'c' does not exist in type '{ a: [EventCallable<{ foo: 2; }>]; b: EventCallable<{ foo: 2; }>; }'.
         "
       `)
     })
@@ -2058,18 +2213,20 @@ describe('array cases', () => {
     const secondTarget: EventCallable<number> = createEvent()
     const defaultarget: EventCallable<number> = createEvent()
     split({
-      //@ts-expect-error
       source,
+      //@ts-expect-error
       match: caseStore,
       cases: {
         a: [firstTarget],
+        //@ts-expect-error
         b: [secondTarget],
         __: [defaultarget],
       },
     })
     expect(typecheck).toMatchInlineSnapshot(`
       "
-      Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match unit should contain case names\\"; need: \\"a\\" | \\"b\\"; got: \\"a\\" | \\"c\\"; }'.
+      Type 'StoreWritable<\\"a\\" | \\"c\\">' is not assignable to type 'Unit<\\"a\\" | \\"b\\">'.
+      Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<number>]; __: [EventCallable<number>]; }'.
       "
     `)
   })
@@ -2079,18 +2236,20 @@ describe('array cases', () => {
     const secondTarget: EventCallable<number> = createEvent()
     const defaultarget: EventCallable<number> = createEvent()
     split({
-      //@ts-expect-error
       source,
+      //@ts-expect-error
       match: (src): 'a' | 'c' => 'a',
       cases: {
         a: [firstTarget],
+        //@ts-expect-error
         b: [secondTarget],
         __: [defaultarget],
       },
     })
     expect(typecheck).toMatchInlineSnapshot(`
       "
-      Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match function should return case names\\"; need: \\"a\\" | \\"b\\"; got: \\"a\\" | \\"c\\"; }'.
+      Type '\\"a\\" | \\"c\\"' is not assignable to type '\\"a\\" | \\"b\\"'.
+      Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<number>]; __: [EventCallable<number>]; }'.
       "
     `)
   })
@@ -2100,27 +2259,85 @@ describe('array cases', () => {
     const secondTarget: EventCallable<number> = createEvent()
     const defaultarget: EventCallable<number> = createEvent()
     split({
-      //@ts-expect-error
       source,
       match: {
         a: src => true,
+        //@ts-expect-error
         c: src => true,
       },
       cases: {
         a: [firstTarget],
+        //@ts-expect-error
         b: [secondTarget],
         __: [defaultarget],
       },
     })
     expect(typecheck).toMatchInlineSnapshot(`
       "
-      Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"match object should contain case names\\"; need: \\"a\\" | \\"b\\"; got: \\"a\\" | \\"c\\"; }'.
+      Object literal may only specify known properties, and 'c' does not exist in type '{ a: (src: number) => true; b: (p: number) => boolean | Store<boolean>; }'.
+      Object literal may only specify known properties, and 'b' does not exist in type '{ a: [EventCallable<number>]; __: [EventCallable<number>]; }'.
+      "
+    `)
+  })
+
+  test('non-inline array in case (should fail)', () => {
+    type A = {tag: 'a'; value: 0}
+    type B = {tag: 'b'; value: 'b'}
+    const source = createEvent<A | B>()
+
+    const $aMatch = createStore(true)
+    const aCase = createEvent<A>()
+    const bCase = createEvent<B>()
+
+    // this works with "as const" modifier, but also should work without it
+    const arrayCase = [aCase, bCase]
+
+    split({
+      // @ts-expect-error
+      source,
+      match: {
+        a: $aMatch,
+      },
+      cases: {
+        // @ts-expect-error
+        a: arrayCase,
+      },
+    })
+    expect(typecheck).toMatchInlineSnapshot(`
+      "
+      no errors
       "
     `)
   })
 })
 
-test('split + attach', () => {
+test('attach in default case (should fail)', () => {
+  const $number = createStore<number>(0)
+  split({
+    //@ts-expect-error
+    source: $number,
+    match: {},
+    cases: {
+      //@ts-expect-error
+      __: attach({
+        source: createStore<any>(null),
+        effect: (_, param: string) => {},
+      }),
+    },
+  })
+  expect(typecheck).toMatchInlineSnapshot(`
+    "
+    Type 'StoreWritable<number>' is not assignable to type 'Unit<string>'.
+      Types of property '__' are incompatible.
+        Type 'number' is not assignable to type 'string'.
+    Type 'Effect<string, void, Error>' is not assignable to type 'UnitTargetable<number>'.
+      Types of property '__' are incompatible.
+        Type 'string' is not assignable to type 'number'.
+    "
+  `)
+})
+
+test('attach in default case (should pass)', () => {
   const $number = createStore<number>(0)
   split({
     source: $number,
@@ -2134,7 +2351,25 @@ test('split + attach', () => {
   })
   expect(typecheck).toMatchInlineSnapshot(`
     "
-    Object literal may only specify known properties, and 'source' does not exist in type '{ error: \\"config should be object with fields \\\\\\"source\\\\\\", \\\\\\"match\\\\\\" and \\\\\\"cases\\\\\\"\\"; got: { source: StoreWritable<number>; match: {}; cases: unknown; clock: unknown; }; }'.
+    no errors
+    "
+  `)
+})
+
+test('inline prepend call in cases (should pass)', () => {
+  const fooFx = createEffect(() => {})
+  const errorSettled = createEvent<'ok'>()
+
+  split({
+    source: fooFx.failData,
+    match: res => 'ok',
+    cases: {
+      __: errorSettled.prepend(() => 'ok'),
+    },
+  })
+  expect(typecheck).toMatchInlineSnapshot(`
+    "
+    no errors
     "
   `)
 })