Skip to content

Please consider enabling exactOptionalPropertyTypes by defaultΒ #60636

Closed as not planned
@allisonkarlitskaya

Description

@allisonkarlitskaya

πŸ” Search Terms

exactOptionalPropertyTypes in the subject line on open and closed issues and PRs in this repository

βœ… Viability Checklist

⭐ Suggestion

exactOptionalPropertyTypes is great, and it's been around for a few years by now. It's a recommended option, and having it off means that | undefined gets implicitly sprinkled around on your types.

I'd like to see this feature enabled by default. It's a clear improvement to the semantics of the language and (with the benefit of hindsight) it probably should have been the way this was done in the first place.

I understand that turning this option on is going to break a lot of existing code (see the above unchecked box edit okay, it forced me to check it), and that this is why it hasn't been done yet. I wonder if the default could be changed to a special mode that's compatible with the old default value (false) but also avoids generating errors caused by undefined not being compatible with other types. See the example below for the specific case where we're getting in trouble.

In general, though, it would be awesome if there was a mechanism to allow advancing "new defaults" for language features, something akin to Rust "editions". That's a way larger question, though.

πŸ“ƒ Motivating Example

The main issue is that if you have this feature on in your codebase you can produce APIs that don't work when people try to import/vendor them into their codebase with that option disabled.

We recently got this bug report: cockpit-project/cockpit#21352

In short, we have a "json" type defined in a rather typical way:

export type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue };
export type JsonObject = Record<string, JsonValue>;

but then we sometimes say things like

export interface BaseChannelOptions extends JsonObject {
    command?: never;
    channel?: never;
    binary?: boolean;
    host?: string;
    payload?: string;
    superuser?: "try" | "require";
}

to produce an interface which is required to never have the properties command or channel present.

This works great with exactOptionalPropertyTypes but if our code gets used by someone who doesn't have that option set they see an error like:

pkg/lib/cockpit/channel.ts:31:3 - error TS2411: Property 'command' of type 'undefined' is not assignable to 'string' index type 'JsonValue'.

πŸ’» Use Cases

See above.

Thanks very much!

Metadata

Metadata

Assignees

No one assigned

    Labels

    DeclinedThe issue was declined as something which matches the TypeScript visionSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions