Thanks for the type predicate explanation. But in my case TS (v.3.8.3) is not happy with isCat function:
functionisCat(animal:Cat|Dog):animalisCat{returntypeofanimal.numberOfLives==='number';// Property 'numberOfLives' does not exist on type 'Cat | Dog'.// Property 'numberOfLives' does not exist on type 'Dog'.(2339)}
What are other options for isCat implementation? I can think of
This works, but numberOfLives is a plain string. It's easy to make a typo or forget to change this string in the process of refactoring. Is there a better option to create the type predicate?
All right, I found that TS has discriminated unions for such cases.
Just extend your interfaces with a common property and use it to narrow types in your code.
interfaceCat{kind:'cat';numberOfLives:number;}interfaceDog{kind:'dog';isAGoodBoy:boolean;}functionisCat(animal:Cat|Dog):animalisCat{returnanimal.kind==='cat';}functiongetAnimal():Cat|Dog{return{kind:'cat',numberOfLives:7}}letanimal=getAnimal();animal.numberOfLives// Error. Property 'numberOfLives' does not exist on type 'Cat | Dog'if(isCat(animal)){animal.numberOfLives// OK}
Thanks for the type predicate explanation. But in my case TS (v.3.8.3) is not happy with
isCat
function:What are other options for
isCat
implementation? I can think ofThis works, but
numberOfLives
is a plain string. It's easy to make a typo or forget to change this string in the process of refactoring. Is there a better option to create the type predicate?All right, I found that TS has discriminated unions for such cases.
Just extend your interfaces with a common property and use it to narrow types in your code.
I use the "as" keyword and then a specific property on the type.
so in your above example you could leave out the "kind" property:
I like not having to add the extra property to my types. :)
Full code for my example found in this file: github.com/mirkoRainer/RulesLawyer...