Note that in Typescript, the `?` suffix is only accepted in specific constructs and has different semantics than just building an optional type.

This can be used to denote optional fields in an interface (somewhat akin to TypedDict) see https://www.typescriptlang.org/docs/handbook/interfaces.html#optional-properties and denote an optional parameter https://www.typescriptlang.org/docs/handbook/functions.html#optional-and-default-parameters, i.e., the parameter does not need to be explicitly passed to the function.

For example, in an interface  bar?: number; is not the same as bar: number | undefined; (see playground):

interface OptionalFields {
    foo: number;
    bar?: number;
}

const test1: OptionalFields = {
    foo: 1
}

interface RequiredButPossibleUndefinedFields {
    foo: number;
    bar: number | undefined;
}

// This is invalid. Compare it to test1
const test4: RequiredButPossibleUndefinedFields = {
    foo: 1
}

In other type declarations, like generics, one needs to use the full spelling, for example Promise<number | undefined>

On Thu, Sep 10, 2020 at 5:31 AM Никита Соболев <n.a.sobolev@gmail.com> wrote:
> My question (which you didn't answer) is which variant should we recommend, and why? I honestly find both `(bytes | str)?` and `bytes? | str?` unpleasant to look at, and the fact that it's not clear which is better makes it even worse. We could even recommend `bytes | str?` but that's even weirder.

Yes, I agree that all `|` variants with `?` do not look too pleasant.
And that multiple possibilities to write the same things make it even worse.

Here I want to show some examples from other languages that already have this feature.

TypeScript. It has both `null` and `undefined`. So, there are two syntax constructs to represent it: `| null` and `?` respectively.
There's a setting to change this a bit, but let's omit it for now. We are going to use the `--strict` version.

function worksWithOptional(param?: number) {}

worksWithOptional(1)
worksWithOptional(undefined)

function worksWithNullable(param: number | null) {}

worksWithNullable(1)
worksWithNullable(null)

function worksWithUnion(param: number | string) {}

function worksWithOptionalUnion(param?: number | string) {}

function worksWithNullableUnion(param: number | string | null) {}

It is clear why TypeScript has both `?` and `| null`, because in JS there are two "empty" states.
But, it is also important to highlight that TypeScript does not have this `str? | bytes` vs `(str | bytes)?` problem.
It either has a single `?` near the argument / property definition, or union with explicit `null`

Flow is a bit different. It allows both `null` and `undefined` to be under `?` when placed in type definition.
And also has `?` near arguments / props to mark them to work with `undefined`, but not `null`.
See https://stackoverflow.com/questions/50112490/what-is-the-difference-between-a-string-and-a-string-in-flow-type
/* @flow */

function foo(x: ?number | string) {}

foo(undefined)
foo(null)
foo(1)

function bar(x: ?(number | string)) {}

bar(undefined)
bar(null)
bar(1)

function baz(x: number | ?string) {}

baz(undefined)
baz(null)
baz(1)

function withOptional(x?: number) {}

withOptional(1)
withOptional(undefined)

It looks way less readable compared to TS.

Scala (which is mentioned in the original PEP) (dotty) has only a single way of doing it: `Int|String|Null` https://dotty.epfl.ch/docs/reference/other-new-features/explicit-nulls.html Currently it is in development and things may change. It has no special syntax for `Null`. Scala usually uses the `Maybe` monad to handle empty states, so there's no need for a special syntax.

Other languages either don't have `?` syntax (like Scala and Julia), or have different `Null` concepts (like Rust and Haskell), or have different Union concepts (like Swift, Kotlin and Rust), or go really wild in terms of syntax like `T.nilable(T.any(Number | String))` in Ruby or `float() | none()` in Elixir.

So, there is nowhere to copy any alternative solutions from. At least in the mainstream languages.

My personal opinion:
1. This looks great, way better than now with `Optional`: `def some(arg: str? = None): ...` compare it with

```
from typing import Optional

def some(arg: Optional[str] = None): ...
```

2. This looks a bit less great: `def other(arg: str | None = None): ...` But still pretty pleasant
3. The union solution (2) does scale. It can easily become `str | bytes | None`
4. The `?` (1) solution does not scale well, as I have shown above, `str?` has trouble becoming `str? | bytes` or `(str | bytes)?`

(I even don't mention other possible types operators like `&` for intersections that can be added later)


чт, 10 сент. 2020 г. в 03:08, Guido van Rossum <guido@python.org>:
The requirement of having a PEP sponsor is to make sure that poorly thought-out proposals are stopped with minimal waste of resources. Your proposal, even though I am not particularly in favor of it, deserves to be a discussion to have. (For example, it seems that TypeScript is surviving even though it also has this problem of how best to write `Optional[Union[...]]`.)

So if you can't find someone else to sponsor it, I will, even though when it comes down to accepting it I would probably recommend that the SC reject it. Even that would be useful, since then we can point to the rejected PEP when the idea is brought up again. :-)

Finally -- wouldn't we need to have a new dunder method/protocol so the operator can be overloaded for other functionality?

On Wed, Sep 9, 2020 at 3:12 PM Maggie Moss <maggiemoss@fb.com> wrote:
Thanks for the feedback. 

One additional question here: Would anyone like to sponsor this PEP?


Thanks, 
Maggie

From: Guido van Rossum <guido@python.org>
Sent: Thursday, September 3, 2020 3:18 PM
To: Maggie Moss <maggiemoss@fb.com>
Cc: typing-sig@python.org <typing-sig@python.org>
Subject: Re: [Typing-sig] Update: Work on Optional Syntax PEP
 
Wow, you've been busy! (I know I still owe you a review on the PEP 604 implementation. It's on my TODO list. :-)

My main observation at this point is that introducing a new token means that there is no way to use this in code that has to be backwards compatible with Python 3.9 and before (assuming you could get it into 3.10). This is different for PEP 604's `|` operator, which can be used in Python 3.7+ as long as the `from __future__ import annotations` magic import is used to avoid runtime errors on things like `int | str`. The `|` operator could also be used in typeshed, since it is valid Python 3.7 syntax. (While I don't know of any type checkers that currently support it yet, supporting it would not require changes to the Python *parser* -- at least typed_ast can handle it without changes.)

However, this shouldn't be a big strike against the proposal. In a few short years Python 3.10 will be the oldest version supported and all will be well.

Another concern I have is that we already have two ways to spell "optional": `Optional[T]` and `T | None`.

Finally, IMO the argument against `Optional[T]` is stronger than the argument against `T | None`. (But your point that 7% of annotations use Optional is well taken.)

--Guido



On Thu, Sep 3, 2020 at 12:04 PM None via Typing-sig <typing-sig@python.org> wrote:
Hi there,

Recently I have been working on an implementation for PEP 604 (https://www.python.org/dev/peps/pep-0604/). While working on this, I started reviewing and exploring what new Optional syntax would look like in the Python language.

I've written a rough draft of a PEP and wanted to present it to this email list before submitting a PR. I know this is a topic that has been discussed in many settings (Github issues, in person typing meetups, etc. )previously, and wanted to solicit feedback here first. Let me know if submitting a PR would be a better way to gauge sentiment and feedback on this proposal.

Draft Proposal (branch compare): https://github.com/python/peps/compare/master...MaggieMoss:optional-syntax-pep
Gist: https://gist.github.com/MaggieMoss/c848cb3a581979f445d075c15629c950

Thanks again,
Maggie
_______________________________________________
Typing-sig mailing list -- typing-sig@python.org
To unsubscribe send an email to typing-sig-leave@python.org
https://mail.python.org/mailman3/lists/typing-sig.python.org/
Member address: guido@python.org


--
--Guido van Rossum (python.org/~guido)


--
--Guido van Rossum (python.org/~guido)
_______________________________________________
Typing-sig mailing list -- typing-sig@python.org
To unsubscribe send an email to typing-sig-leave@python.org
https://mail.python.org/mailman3/lists/typing-sig.python.org/
Member address: n.a.sobolev@gmail.com
_______________________________________________
Typing-sig mailing list -- typing-sig@python.org
To unsubscribe send an email to typing-sig-leave@python.org
https://mail.python.org/mailman3/lists/typing-sig.python.org/
Member address: skreft@gmail.com


--
Sebastian Kreft