Skip to content

Prop that is possibly undefined cannot be defaulted to undefined when exactOptionalPropertyTypes and strictNullChecks are true #13593

Open
@Dylancyclone

Description

@Dylancyclone

Vue version

3.5.17

Link to minimal reproduction

https://play.vuejs.org/#eNp9UtFOGzEQ/JWVXwoSuqiiVaXooGppHtoHiFoeLVXWZXM58NlmvU5ygvt31j4ISCB0L/bM2Dcz63v1I4Rqm1DNVR0b6gJDRE4BrHHtmVYctTrXTrvGu8gQyIcIZ7DrePML1yZZjkdC8wrXncNlpuv7DGiOTJ1rM/R9DtMGHiC5SbqC2QyunB3AB+68MxaiB94gLK0ZWvIihJXH6D6JJTNA38WYryC8Sx3J+eylggWRJ/BNkygCii0k2JkhWxjPj45P8uKNofmLjSIYtTvWrp5NDZS8NWMfrGGUXT17tVEnUoq0se7a6iZ6J83J/QBaNb4PnUW6KoGkuDkUJnPGWr/7UzCmhPLXCW822Ny+g9/Efca0WhJGpC1qdeDYUIs80Yt/l7iX9YHs/SpZUX9A/sXobcoeJ9lPKUNsv9IVt7/74Imlseu42DO6+BzqyWj5pFatcG8anlIbm/tF4uF6CPg2V55Bw5fJ2ouc/CDI/FhUWslzvPigypf4p9WXck67Uabyf4uUPcpATquv1edvanwE4tr+Eg==

Steps to reproduce

  1. In your tsconfig.json, under compilerOptions, enable exactOptionalPropertyTypes and strictNullChecks
    • Note: Setting "strict": true will also enable strictNullChecks and cause the issue
  2. In a component, create a prop whose type is possibly undefined, and then set it's default value to be undefined

Example:

const props = withDefaults(
	defineProps<{
		stringProp: string | undefined
	}>(),
	{
		stringProp: undefined,
	}
)
  1. Notice the error:
Argument of type '{ stringProp: undefined; }' is not assignable to parameter of type 'InferDefaults<LooseRequired<__VLS_Props>>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
  Types of property 'stringProp' are incompatible.ts(2379)

...even though 'undefined' has been added to the types of the target's properties.

What is expected?

When a prop's type is possibly undefined, it should be possible to set it's default value as undefined. This functionality is correct when the TSConfig options exactOptionalPropertyTypes and strictNullChecks are not true

What is actually happening?

You cannot set a prop's default value to undefined even if it's listed as a possible type. The error even suggests adding undefined to the type definition even though it's already there

System Info

System:
    OS: Linux 6.13 Ubuntu 24.04.2 LTS 24.04.2 LTS (Noble Numbat)
    CPU: (8) x64 Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz
    Memory: 4.61 GB / 15.27 GB
    Container: Yes
    Shell: 5.2.21 - /usr/bin/bash
  Binaries:
    Node: 22.14.0 - ~/.nvm/versions/node/v22.14.0/bin/node
    Yarn: 1.22.21 - ~/.nvm/versions/node/v22.14.0/bin/yarn
    npm: 10.9.2 - ~/.nvm/versions/node/v22.14.0/bin/npm
  npmPackages:
    vue: ^3.0.0 => 3.5.17

Any additional comments?

One reason why we'd want to set a default to be undefined is to satisfy this Vue ESLint rule to require optional props have a default set.

It appears this issue comes from the InferDefault type:

type NativeType = null | number | string | boolean | symbol | Function
type InferDefault<P, T> =
| ((props: P) => T & {})
| (T extends NativeType ? T : never)

Any "Non-Native" types are filtered out and instead required to be defined as a function (to account for objects, arrays, and other mutable reference types, see the first info block under this section in the docs).

For some reason, this also filters out undefined, even though it is a primitive JavaScript value?

We testing added undefined to the NativeType type locally and this resolved our issue, though we're not sure if this is the right approach and would like feedback before opening a PR.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions