1

I was reading the official Typescript documentation and came across this example in the type predicate section:

function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}

I think I understand type predicates, but don't understand the pet as Fish1 part. In this code snippet, isn't the programmer lying to typescript just to get the predicate to work? It seems to me the isFish function that returns the predicate is telling typescript "this is a Fish" so that it won't throw a TypeError because the so-called Fish isn't guaranteed to have a swim method. Is this understanding correct :)

5
  • 1
    If pet.swim !== undefined then it must be a Fish. But in order for TypeScript to allow you to access the swim property on pet, you need to assert pet type as Fish. Commented Dec 11, 2022 at 23:35
  • Whether this is "lying" seems like a philosophical question, not a practical question with a definite answer. You can interpret as as meaning an assertion that the value has a certain type, in which case that assertion is a lie (assuming the programmer understands that it isn't true). Or you can interpret it as a request for the compiler to not type-check the expression it occurs in, and a request cannot be a lie. A formalist might interpret it as having no meaning except for what the compiler does with it. Commented Dec 11, 2022 at 23:37
  • Does this answer your question? Class type check in TypeScript Commented Dec 11, 2022 at 23:38
  • In some sense you are right, although I wouldn't call it "lying". Commented Dec 11, 2022 at 23:38
  • At the line,(pet as Fish), there is a good chance that pet will not actually be a Fish. Commented Dec 11, 2022 at 23:43

1 Answer 1

3

its true, that this isnt really a clean solution, i suppose this is done to differentiate the example from the in operator mentioned earlier. Also it might be to illustrate that you can do whatever you want to assert that the object is question is of a particular type, because thats the whole purpose of type predicates.

a cleaner implementation of this function would indeed use the in operator instead of a type assertion imo:

function isFish(pet: Fish | Bird): pet is Fish {
  if ('swim' in pet)
     // possibly do more stuff to check its really a Fish, pet is already narrowed to type Fish in this case
    return true
  else 
    return false
}

edit:

also the type assersion allows you to freely do stuff with the pet in question, writing everything typesafe using ins for exampe can be a bit cumbersome if you work with complex types, especially when the whole purpose is to assert it is in fact some given type

Sign up to request clarification or add additional context in comments.

3 Comments

if ... return true else return false is even cleaner as return ...
@WiktorZychla is that like, sarcasm? i did it intentionally here to illustrate that you can do more stuff in the type narrowed block here, generally id say if (predicate) return true else return false is an antipattern if used without purpose and should be replaced by return predicate
is that like, sarcasm Not at all, I am one of the two upvoters. It's a good answer but remember that less experienced developers (and AI) come here to learn. If there's something that could improve an answer, we comment each other so that answers become even better. My impression is that someone less experienced could miss the subtlety of yours and making it more explicit would improve the answer.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.