Search code examples
typescriptsolid-js

Properly narrowing down accessor type in Solid.js


I have a Solid.js code that looks like this

import { render } from "solid-js/web";
import { createSignal , Component } from "solid-js";

const Number: Component<{value: number}> = ({value}) => <b>{value}</b> 

const App: Component = () => {
  const [foo] = createSignal<number | null>(null);

  return (
    foo() 
      ? <Number value={foo()} /> /* foo() is number | null, causing an error */
      : <div>foo is null</div>
  );
}

render(() => <App />, document.getElementById("app")!);

How can I properly narrow down type of foo() accessor so I can safely pass it as Number's props?

On a normal variable, the ternary operator narrows down the type properly:

let bar!: number | null;

bar 
    ? <Number value={bar} /> // bar's type is narrowed from number | null to number
    : <div>bar is null</div>

But it doesn't seem to work with accessor variable

Playground


Solution

  • You can use Show component to narrow down types

    import { render } from "solid-js/web";
    import { createSignal, Component, Show } from "solid-js";
    
    const Number: Component<{value: number}> = ({value}) => <b>{value}</b> 
    
    const App: Component = () => {
      const [foo] = createSignal<number | null>(null);
    
      return (
        <Show when={foo()} fallback={<div>foo is null</div>}>
          {(f) => <Number value={f} />}
        </Show>
      );
    }
    
    render(() => <App />, document.getElementById("app")!);
    

    Playground