【问题标题】:What's the difference between Accessor<SomeType> and just SomeType in Typescript?Accessor<SomeType> 和 Typescript 中的 SomeType 有什么区别?
【发布时间】:2023-01-10 01:38:29
【问题描述】:

我正在使用 Solid 在 Typescript 中做一个待办事项列表应用程序。我定义了一个Todo类型如下:

type Todo = {
  text: string;
  complete: boolean;
};

稍后我想检查一下当天要做的所有事情是否都完成了,这样我就可以增加我的连胜纪录。为此,我使用本地存储:

const [state, setState] = createStore<{days: number, todos: Todo[]}>({
  days: 0,
  todos: todos,
});

但是后来TS说最后todos有问题:类型“Accessor<Todo[]>”不可分配给类型“Todo[]”。

所以,我的问题是,我的Todo[] 和另一个Accessor&lt;Todo[]&gt; 有什么区别?这个访问器来自哪里?我可以/应该以某种方式转换它吗?

【问题讨论】:

    标签: typescript types frontend type-conversion solid-js


    【解决方案1】:

    在 solidJS 中,Accessor 是这样定义的:

    type Accessor<T> = () => T;
    

    所以 Accessor&lt;Todo[]&gt; 是一个返回 Todo[] 的函数。至于如何解决这个问题,我需要查看如何创建 todos 变量以给出具体细节,但显然 todos 是一个函数,而它需要是一个数组。也许您只需要调用该函数:

    const [state, setState] = createStore<{days: number, todos: Todo[]}>({
      days: 0,
      todos: todos(),
    });
    

    或者您可能需要在定义 todos 的地方进行更改。

    【讨论】:

      【解决方案2】:

      访问器是一个函数,它返回信号中存储的值。

      type Accessor<T> = () => T;
      

      与 React 不同,Solid 不使用虚拟 DOM,也不会在状态更新时重新渲染。所以它需要函数调用来获取信号的值。这就是 Solid 实现反应性的方式。

      createSignal 函数返回一个带有[Accessor&lt;T&gt;, Setter&lt;T&gt;] 的数组。

      const [item, setItem] = createSignal(10);
              ^
      //    This is an Accessor<T>
      
      // To get the stored value, you need to invoke the accessor
      console.log(item());
      

      createStore 在内部使用一个信号,它返回一个带有访问器和设置器的数组。但是它的访问器使用代理对象,该代理对象将其属性访问委托给内部信号。

      const [todos, setTodos] = createStore([]);
              ^
      //    This is a proxied object, not a plain value T
      

      由于只有对象和数组支持 Proxy API,因此您只能使用具有 createStore 功能的对象或数组。

      createStore 函数的导出类型签名不是派生的,而是手动键入以抑制并发症:

      function createStore<T extends object = {}>(...[store, options]: {} extends T ? [store?: T | Store<T>, options?: {
          name?: string;
      }] : [store: T | Store<T>, options?: {
          name?: string;
      }]): [get: Store<T>, set: SetStoreFunction<T>];
      

      似乎您正在尝试在商店中存储一个信号,这就是您获得该警告的方式,但商店价值本身是反应性的,并实现了所有必要的 API 来插入、删除和更新项目。避免存储信号,因为您会引入完全不必要的抽象层。

      【讨论】:

      • 哇,这是有道理的。谢谢,真的很有帮助。
      • 很高兴有帮助。请将其标记为已接受,以便其他人可以受益。有许多遗漏的 SO 问题不能很好地反映社区。
      猜你喜欢
      • 2022-01-03
      • 1970-01-01
      • 1970-01-01
      • 2011-07-23
      • 1970-01-01
      • 1970-01-01
      • 2011-03-06
      • 2021-08-18
      • 2014-02-26
      相关资源
      最近更新 更多