Edit: As some other answers allude to, the behavior has changed. If you're interested here is the relevant Angular source code:
const TRUE_BOOLEAN_VALUES = new Set<string>(['true', '1']); const FALSE_BOOLEAN_VALUES = new Set<string>(['false', '0']); function makeLambdaFromStates(lhs: string, rhs: string): TransitionMatcherFn { const LHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(lhs) || FALSE_BOOLEAN_VALUES.has(lhs); const RHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(rhs) || FALSE_BOOLEAN_VALUES.has(rhs); return (fromState: any, toState: any): boolean => { let lhsMatch = lhs == ANY_STATE || lhs == fromState; let rhsMatch = rhs == ANY_STATE || rhs == toState; if (!lhsMatch && LHS_MATCH_BOOLEAN && typeof fromState === 'boolean') { lhsMatch = fromState ? TRUE_BOOLEAN_VALUES.has(lhs) : FALSE_BOOLEAN_VALUES.has(lhs); } if (!rhsMatch && RHS_MATCH_BOOLEAN && typeof toState === 'boolean') { rhsMatch = toState ? TRUE_BOOLEAN_VALUES.has(rhs) : FALSE_BOOLEAN_VALUES.has(rhs); } return lhsMatch && rhsMatch; }; }
It's a little tricky to follow unless you're debugging it yourself but basically the important thing to notice is that fromState and toState are the values (when there is a change) that you set on the animation in the template: eg. [@animation]="animationState"
So you can see they explicitly allow them to be booleans (typeof fromState === 'boolean').
The reason I got caught out (and found my way back to my own old answer) is that Angular's AnimationEvent defines them as strings:
/** * The name of the state from which the animation is triggered. */ fromState: string; /** * The name of the state in which the animation completes. */ toState: string;
So therefore on completion of an animation where your state is set to a boolean (eg. true / false and NOT 'true' / 'false' you'll run into a typing issue.
The actual value of event.fromState may be true so
event.fromState == true gives a compiler error ('string' and 'boolean' have no type overlap) event.fromState == 'true' will NEVER be true (since the value is actually true)
So you'd need to either use:
if (<any>(event.toState) == true)
OR
if ((event.toState as string | boolean) == true)
Old answer:
A state is defined as being a string, so we need to stick to that.
The simplest - but ickiest - way based on your code is this
<div [@trueFalseAnimation]="model.someProperty?.toString()">Content here</div>
But this is pretty awful, so this is probably better
<div [@trueFalseAnimation]="model.someProperty ? 'active' : 'inactive'">Content here</div> <div [@trueFalseAnimation]="model.someProperty ? 'visible' : 'hidden'">Content here</div> <div [@trueFalseAnimation]="model.someProperty ? 'up' : 'down'">Content here</div> <div [@trueFalseAnimation]="model.someProperty ? 'left' : 'right'">Content here</div>
The best advice here would be to use a state that corresponds to what it really means. What does true and false really mean in this context anyway?
I considered making a pipe to convert a boolean, but the only benefit of that would be to make sure you're being consistent with your state strings.