如何在 Vue 组件数据上维护正确的打字稿类型?

How to maintain proper typescript type on Vue component data?

我正在开发一个 Vue 项目,我正在使用打字稿更新到 Vue 3。我发现打字稿 parser/compiler 有一个奇怪的行为。我有以下组件:

    export default defineComponent({
        name: 'Test',

        data() {
            return {
                test: new Child(),
            };
        },
        
        methods: {
            testMethod: function () {
                this.test = new Child(); 
                let test2 = new Child();
            }
        },
    });


    class Child {
        b = 0;
    }

方法中,解析器认为test2Child类型。但它认为 this.test{b: number} 类型(即它已经失去了与 Child 的连接。将鼠标悬停在数据结构 (vscode) 上表明当它在那里创建时它认为类型是 Child.

在这个例子中,这不是真正的问题,因为它可以很容易地施放它。但是如果 Child 被定义为:

  class Parent {
     private a = 1;
  }
  class Child extends Parent {
     b = 0;
  }

然后 this.test 仍然具有相同的类型 {b:number}(它失去了私有成员)并且不能再转换为 Parent。这会导致无休止地类型转换为 any 以解决问题。它没有选择正确类型的另一个症状是 this.test.a = 3 生成 属性 不存在 (ts2339)test2.a = 3; 生成 属性 是私有的,只能通过父级 (ts2341) 访问(这是正确的错误)。

我也尝试手动指定 return 类型的 data(),结果相同。

我做错了什么吗?这就是 Vue 插件与 Typescript 一起工作的方式吗?

here 所述,问题是 data 项是反应性的,而在 wrapping/unwrapping 中,class 丢失了。

那里的解决方案表明指示使用 shallowRef() (因为对于如此复杂的东西,通常首选保持实例原始):

export default defineComponent({
        name: 'Test',

        setup() {
            return {
                test: shallowRef(new Child()),
            };
        },

      ...
        
    });

如果您不介意(或更喜欢)包装器,只需将 data 更改为 setup 即可解决输入问题:

export default defineComponent({
        name: 'Test',

        setup() {
            return {
                test: new Child(),
            };
        },
        
        ...
    });