Subscribe on changes!

When using TypeScript, BigInt is not usable as a component prop type.

avatar
Mar 30th 2022

Version

3.2.31

Reproduction link

github.com

Steps to reproduce

Create a project with npm init vue@latest, configure it to use TypeScript, set the tsconfig and vite config to target ES2020, and then add a prop to one of the components whose type is BigInt (see TheWelcome.vue in the reproduction link). The ES2020 configuration is required for BigInt to be recognized in the first place. Run either npm run build or npm run typecheck to see the errors.

What is expected?

Setting a prop's type to BigInt should just work (tm)

What is actually happening?

Type errors, and compilation failures. Notably the prop definition line shows the following error:

error TS2769: No overload matches this call.
  The last overload gave the following error.
    Type 'BigIntConstructor' is not assignable to type 'Prop<unknown, unknown> | null'.
      Type 'BigIntConstructor' is not assignable to type '() => unknown'.

This issue exists despite the announcement here and the closed issue here.

A workaround is to define a wrapper class and use propname: Object as PropType<MyWrappe>. Then wrap the bigint in a method when passing it in as a prop, and access the inner class field when reading the prop.

avatar
Mar 30th 2022

Note: a better and far less intrusive workaround would likely be:

props: {
  whatever: BigInt as unknown as PropType<BigInt>
}

We likely didn't include BigInt as Vue 3 is aiming to be compatible with ES2016+. If I'm not mistaken, including BigInt into our types would require projects to have "target": "es2020" or higher set, which likely not everyone has.

So we should not change this in a patch release.

@pikax Thoughts?

avatar
Mar 30th 2022

RE workaround: Thanks, I didn't consider that! your suggestion almost worked, it should be spelled like this, with a lowercase typename in the PropType:

props: {
  whatever: BigInt as unknown as PropType<bigint>
}

any also works instead of unknown

avatar
Apr 1st 2022

@pikax Thoughts?

Surprised it didn't work, we don't do much magic here:

type PropConstructor<T = any> =
  | { new(...args: any[]): T & {} }
  | { (): T }

declare function test<T>(a: PropConstructor<T>): T;

test(Boolean)
test(String)
test(BigInt) // fails

playground

From what I can see the BigInt has a different format than the other constructors (eg: String, Boolean, Object, etc)

interface StringConstructor {
    new(value?: any): String; // he have this here
    (value?: any): string;
 //...
}

interface BigIntConstructor {
    (value: bigint | boolean | number | string): bigint; // missing the new(value): BigInt
    //...
}

I think the fix would require us to add a explicit check for BigInt and for that we would need to bump the target I suppose

avatar
Apr 2nd 2022

I think a good short-term solution could be to just add a comment showing the workaround above to this section of the docs: https://vuejs.org/guide/typescript/options-api.html#typing-component-props

avatar
Apr 21st 2022

You can annotate components prop types using TypeScript。 reference: https://vuejs.org/guide/typescript/composition-api.html#typing-component-props

defineProps<{ num: bigint }>