When using TypeScript, BigInt is not usable as a component prop type.
Version
3.2.31
Reproduction link
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.
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?
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
@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
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
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
You can annotate components prop types using TypeScript。 reference: https://vuejs.org/guide/typescript/composition-api.html#typing-component-props
defineProps<{ num: bigint }>