9

Let's take the classical example of a function that may return a number or not.

In typescript this can be represented like this:

function f(): number | undefined {}

A more elaborate way would be to build a maybe type and use that for the typing:

type Maybe<T> = T | undefined;

function f(): Maybe<number> {}

To check the type of the returned value we could use an if:

const x = f();
if (x === undefined) { } else {}

Is there a conventional way to express the optional type in typescript?

Is there a better way to check the type of the return object?

3
  • 2
    You can use a Js promise as a maybe monad in most situations. Commented Jan 16, 2019 at 21:28
  • I'm not sure I understand what you mean, a promise with which signature? Or you would use the exception case (catch) in place of undefined? Commented Jan 17, 2019 at 11:44
  • A promise either has a reject case or a resolve case. Your resolve case would give you the value and your reject case would be undefined. In this case, your function would return a Promise<Number> which could resolve into the number or get rejected Commented Jan 17, 2019 at 19:27

1 Answer 1

8

To your second question, using === for comparing a type with a single value is imho good practice in TypeScript. There are other ways to check for certain types which are more involved and overkill for this particular use, but there's a good blog post about it here. So to your first question, what is the standard way?

There is a type Option, defined in prelude-ts, which you might consider canonical. It has the definition:

type Option<T> = Some<T> | None<T>;

The type of your function would be:

function f(): Option<number> {}

Note that the extra <T> for None allows type reasoning to distinguish between, say, no string and no number.

In your examples you are using undefined for None<T>. Aside from the above, this has the drawback of giving less type safety when comparing values that are statically both known to be undefined. If you don't care about this, and insist on using a JavaScript value for None, consider using null instead of undefined, this at least gives you the advantage of being able to distinguish between uninitialised values and null values on a type level:

if(x === undefined){
  // succeeds if x is of type 'SomeT | undefined' but is undeclared
}
if(x === null){
  // type error for reading x, if the type of x is 'SomeT | null' and x is undeclared
  // success if x is null.
}

Which of the discussed options is best? Mathematically, the only thing equal to the maybe monad is the one as in prelude-ts: it is the only definition that allows you to distinguish no-string from no-number on a type level.

2
  • Very interesting! My 2 questions would be1) when you say prelude-ts is canonical, do you mean it's commonly used in real world project? Do you know some open source project using it? 2) By taking a look at the project on github, it appears that the suggested way to check an option value would be with the match function. Is it correct? In that case it looks a little bit "distant" from standard javascript/typescript. Commented Jan 17, 2019 at 14:19
  • I'm not sure how much prelude-ts is used in real world projects, I can see that it is downloaded a lot, and it describes a section that indicates that it looked at related libraries as well, all of which use the option monad this way. Prelude-ts may or may not be canonical, but it's way of defining the option monad is used by many. The match function is coming from pattern matching like in Haskell and Scala; indeed it is a bit distant from javascript, but it is closer to several strongly typed languages. I cannot say how canonical it is, but I like it!
    – Sebastiaan
    Commented Jan 21, 2019 at 12:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.