From 3c666467c8e5388d5408d431d5e2f5b639bbfb48 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Sun, 18 Aug 2019 18:02:54 +0200 Subject: [PATCH] Model in modelView does not have to return ReactivesObject --- src/component.ts | 24 +++++++++++++++++------- test/component.spec.ts | 9 +++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/component.ts b/src/component.ts index 42bffd4..5e308ab 100644 --- a/src/component.ts +++ b/src/component.ts @@ -230,10 +230,20 @@ export function isComponent(c: any): c is Component { return c instanceof Component; } +type Reactive = Behavior | Stream | Future; + export interface ReactivesObject { - [a: string]: Behavior | Stream | Future; + [a: string]: Reactive; } +/** + * Removes all properties from a type except those that are either + * streams, behaviors, or futures. + */ +type OnlyReactives = { + [K in keyof R]: R[K] extends Reactive ? R[K] : never; +}; + const placeholderProxyHandler = { get: function(target: any, name: string): Behavior | Stream { if (!(name in target)) { @@ -336,7 +346,7 @@ function addErrorHandler(modelName: string, viewName: string, obj: any): any { }); } -class ModelViewComponent extends Component< +class ModelViewComponent, V> extends Component< M, {} > { @@ -381,20 +391,20 @@ class ModelViewComponent extends Component< export type ModelReturn = Now | Iterator; export type Model = (v: V) => ModelReturn; export type Model1 = (v: V, a: A) => ModelReturn; -export type View = (m: M) => Child; -export type View1 = (m: M, a: A) => Child; +export type View = (m: OnlyReactives) => Child; +export type View1 = (m: OnlyReactives, a: A) => Child; -export function modelView( +export function modelView, V>( model: Model, view: View, toViewReactiveNames?: string[] ): () => Component; -export function modelView( +export function modelView, V, A>( model: Model1, view: View1, toViewReactiveNames?: string[] ): (a: A) => Component; -export function modelView( +export function modelView, V>( model: any, view: any, toViewReactiveNames?: string[] diff --git a/test/component.spec.ts b/test/component.spec.ts index a558c4f..f7970aa 100644 --- a/test/component.spec.ts +++ b/test/component.spec.ts @@ -367,6 +367,15 @@ describe("modelView", () => { expect(dom.querySelector("span")).to.not.exist; expect(toplevel).to.equal(true); }); + it("model can return non-reactive but the view can't use it", () => { + const c = modelView( + ({}) => H.Now.of({ foo: H.Behavior.of("foo"), bar: "bar" }), + // Using `bar` in the view below would give a type error. + ({ foo }) => span(["World", dynamic(foo)]) + )(); + const { available } = testComponent(c); + assert.strictEqual(available.bar, "bar"); + }); }); describe("view", () => {