Subscribe on changes!

Argument of type 'symbol' is not assignable to parameter of type 'string | unique symbol'

avatar
Oct 4th 2022

Vue version

3.2.40

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-fpdjeq?file=package.json%2Csrc%2Fcomponents%2FHelloWorld.vue%2Cindex.html&terminal=dev

Steps to reproduce

  • Run reproduction.
  • Run vue-tsc (or as configured in reproduction, use vite-plugin-checker)

What is expected?

Type checking succeeds.

What is actually happening?

Type checking fails with:

Argument of type 'symbol' is not assignable to parameter of type 'string | unique symbol'.

I am not sure why type of NONE changes inside the template.

System Info

This is a type checking issue and not related to a particular browser.

  System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 16.14.2 - /usr/local/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 7.17.0 - /usr/local/bin/npm
  npmPackages:
    vue: ^3.2.40 => 3.2.40 
avatar
Oct 4th 2022

Workaround is to create two helper functions:

function onNoneChange(event: Event) {
  onChange(event, NONE)
}

function stateHasNONE(): boolean {
  return props.state.includes(NONE)
}

This should not be necessary.

avatar
Oct 4th 2022

Using NONE instead of this.NONE can resolve it temporarily. Maybe you can try this as an interim solution.

// HelloWorld.tsx
import { defineComponent, PropType } from "vue";
const NONE: unique symbol = Symbol('NONE')
type State = (string | typeof NONE)[];

export default defineComponent({
  props: {
    state: {
      type: Array as PropType<State>,
      required: false
    }
  },
  emits: {
    'update:state': (state: State) => true
  },
  setup() {
    const NONE_ERR: unique symbol = Symbol('NONE')

    const onChange = (e: Event, val: typeof NONE) => {
      console.log(val)
    }
    return {
      NONE_ERR,
      onChange,
    }
  },
  render() {
    type aaa = typeof this.NONE_ERR // symbol
    type bbb = typeof NONE // unique symbol
    return <input type="text" onClick={(e) => this.onChange(e, NONE)} />
  }
})

I think the reason is typeof can't infer the key of obejct is unique symbol .

const thisObj = {
      NONE_ERR,
      onChange,
 }
 type RawBindings = typeof thisObj
 // {
 //   NONE_ERR: symbol;
 //   onChange: (e: Event, val: typeof NONE) => void;
 // }
avatar
Oct 8th 2022

@johnsoncodehk do you know if this bug is related to vue-tsc? It's as if the type of NONE becomes just a regular symbol within the template

avatar
Oct 8th 2022

@posva this is expected behavior because in template NONE access via component context, and NONE type is change from unique symbol to symbol in setup return. It can reproduce with:

import { defineComponent } from 'vue';

const NONE: unique symbol = Symbol('none');
const Comp = defineComponent({
  setup() {
    return { NONE };
  },
});

onChange((new Comp()).NONE)

function onChange(id: typeof NONE) { }

A hack way is indirect expose NONE type to template:

<script lang="ts" setup>
const NONE: unique symbol = Symbol('none');
type NONE_Type = typeof NONE;
</script>

<template>
  <input type="checkbox" @change="onChange($event, NONE as NONE_Type)" />
</template>
avatar
Sep 20th 2023