Paul-Sebastian Manole
Paul-Sebastian Codes

Paul-Sebastian Codes

Why isn't "string?" allowed as a function return value in TypeScript?

Photo by Evan Dennis on Unsplash

Why isn't "string?" allowed as a function return value in TypeScript?

Quick notes on optional parameters and properties in TypeScript

Paul-Sebastian Manole's photo
Paul-Sebastian Manole
ยทNov 20, 2022ยท

3 min read

Subscribe to my newsletter and never miss my upcoming articles

I've recently came upon this question on r/typescript: Why isn't "string?" allowed as a function return value, but instead it needs to be defined like "string | undefined"? and I thought I should blog about this too as I have pondered this question myself in the past. What follows is more or less what I've replied on Reddit.

So why is string? an invalid notation?

You should first know that undefined, like string (not to be confused with the String object) is a primitive JavaScript type.

SomeProperty? is a TypeScript notation. The ? suffix in TypeScript means to be optional.

This meaning is then translated based on its use.

If you declare a property on a TypeScript type or interface as property?: string, it means that the property is either not defined at all, or if it is defined, it is a string. Because it is possibly not defined, you don't need to specify it when you instantiate an object of that type.

If you instead declare it as property: string | undefined, then you have to declare and assign a value or undefined to it when you instantiate an object of that type. The property itself is declared and present on the resulting object but may not contain a value if you assigned undefined to it.

You can't forget to assign something to a property: string | undefined, like you can forget to return something from a function and it implicitly returns undefined. The TypeScript compiler won't allow it.

So... you cannot declare function argument types, function return types and variable types as optional! The types themselves are NEVER optional! It is properties only that can be optional!

Examples

Here are some examples of invalid syntax of optional types and the current TS compiler errors (v4.8.4, some are misleading, I know ๐Ÿคทโ€โ™‚๏ธ):

const opConst: string? = ""; // JSDoc types can only be used inside documentation comments.(8020)

function f(x: string?) {} // JSDoc types can only be used inside documentation comments.(8020)

function g(x: string): string? {
  return undefined;
} // '{' or ';' expected.(1144)

interface IFace {
  IsThisMeantToBeOptionalOrWhat: string?
} // JSDoc types can only be used inside documentation comments.(8020)

And here are the correct versions:

const opConst: string | undefined = "";

function f(x: string | undefined) {} // required param that can be explicitly assigned undefined

function f(x?: string) {} // optional param defaulting to undefined

function g(x: string): string | undefined {
  return undefined;
}

interface IFace1 {
  NotOptional: string | undefined
}

interface IFace2 {
  Optional?: string
}

Pay close attention to the last two interface declarations.

In the first interface, the property is not optional, it must exist but its value can be undefined, and whenever it is undefined, it must be assigned that value explicitly.

In the second interface, the property is completely optional, meaning that you can omit to declare it in object initializations. The resulting type though is the same as in the first interface, a string | undefined.

I guess what you gain here is the possibility to omit the allocation of memory for another property on an object, which may or many not be used.

References

When in doubt about TypeScript, always check the handbook first.

Optional properties

Optional parameters and rest parameters

The TypeScript Handbook

I hope this short article helped you understand TypeScript better. If not, leave a comment and I will try to improve it.

ย 
Share this