Reputation: 2769
To define class property as optional I can use question mark or Maybe
type type Maybe<T> = T | undefined
class Animal {
mouth: Maybe<Mouth>
}
or
class Animal {
mouth?: Mouth
}
Is there a difference?
Upvotes: 0
Views: 145
Reputation: 20142
The difference is that optional field allows for not having the field at all, where T | undefined
forces to have a field with explicit undefined
or T
. Check below difference:
{
// explicit undefined version
type Maybe<T> = T | undefined
type Mouth = {test:string}
class Animal {
mouth: Maybe<Mouth>
}
const animal: Animal = { } // error
const animal2: Animal = {
mouth: undefined
} // fine as it is explicit undefined
}
// optional field version
type Maybe<T> = T | undefined
type Mouth = {test:string}
class Animal {
mouth?: Mouth
}
const animal: Animal = { } // fine
const animal2: Animal = {
mouth: undefined
} // fine
This clearly shows that mouth?
is more wide definition in terms of the the possible values than mouth: Mouth | undefined
. field?
makes object without the field to be assignable to the defined type, where explicit undefined
forces to deal with the field
.
What to choose? It depends but in most cases optional field is the way to go, as it is less restrictive for assignability. The use case for explicit undefined
would be some operation where we enumerate over object keys, or for example we want to tell that this field was cleared in let say PATCH request. Probably we can find more use cases for that but cannot find them in my head now.
BTW. Common construct know as Maybe type is disjoint union, and not simple union. So the definition can look like that:
type Maybe<T> = {tag:"just", value:T} | {tag:"nothing"}
More common name for T | undefined
or T | null
would be Nullable. But this is another topic.
Upvotes: 2
Reputation: 2368
Both will have an optional type but for Maybe<>
you have to unwrap the value safely to get a guaranteed value. So I would suggest you to use the ?
for optional values in your code.
Upvotes: 0