Skip to content

[@vue/reactivity][typing] Unwrapping breaks classes with private fields. #2981

@nandin-borjigin

Description

@nandin-borjigin

Version

3.0.5

Reproduction link

https://codesandbox.io/s/refvalue-strips-off-all-private-fields-2ws44?file=/src/index.ts

Steps to reproduce

import { ref, Ref } from "@vue/reactivity";

class Foo {
  public bar = 1;
  private baz = "a";
}

// Case 1:
interface FooSerivce {
  readonly foo: Ref<Foo>;
}

class FooServiceImpl implements FooSerivce {
  // error: Type 'Ref<{ bar: number; }>' is not assignable to type 'Ref<Foo>'
  foo = ref(new Foo());
}

// IRRELEVANT: consuming the class to get rid of no-unused-vars warning.
new FooServiceImpl();

// Case 2:
class FooService2 {
  foo = ref(new Foo());
}

const fooService = new FooService2();

function fooUi(props: { foo: Foo }) {
  // mimicing a render mechanism here,
  // it's not relevant to the issue.
  return `<h1>${props.foo.bar}</h1>`;
}

// Type '{ bar: number; }' is not assignable to type 'Foo'
fooUi({ foo: fooService.foo.value });

/**
 * It's true that we won't need those private fields
 * when consuming the returned ref. But the real case of
 * the `Foo` class in this demo is often some class provided
 * by a 3rd party library and we cannot modify it.
 * Further, the private field isn't necessarily direct member of
 * the wrapped variable type, it could be deep.
 * See realistic-example.ts for more realistic example.
 */

What is expected?

Type system is happy with either of the cases.

What is actually happening?

Type system is complaining


A naive suggestion is to change the definition of Ref generic type to truly reflect the return type of ref function, as the problem is caused by the mis-alignment between the actual return type of ref function and the Ref type definition. ref function's return type involves Mapped types while Ref<T> simply has a member value of type T.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions