Angular #input property ending with exclamation point? - javascript

This source code has #Input properties that end with a !. Here's an example:
#Input() token!:StripeToken
Why is it useful to have the ! in this case? Some of the comments have noted that it is a non null assertion operator, but why is it useful (Or perhaps not useful) to have that in this particular scenario?
I think the answer to this is that for Angular #Input properties having the non null assertion at the end of the property never makes sense but I wanted to see what the rest of you thought?
Update
I tried it on a new Angular project and I get this error:
A definite assignment assertion '!' is not permitted in this context.ts(1255)
So I don't think that it ever makes sense to inlude the ! operator on an #Input property. Here's a screenshot:

They use the compiler option strictPropertyInitialization so any class property not declared with type undefined and not initialized directly or in a constructor produces error TS2564.
To prevent this compiler error they use the definite assignment assertion modifier which tells TypeScript
... that a variable is indeed assigned for all intents and purposes,
even if TypeScript’s analyses cannot detect so.
Demo
Further reading: https://mariusschulz.com/blog/strict-property-initialization-in-typescript#solution-4-definite-assignment-assertion
Regarding your update
You didn't specify a type for the title variable in your example, that's why you get error TS1255. Using ! in this context is possible and makes sense!

Related

What does the ! mean in the angular syntax? [duplicate]

This question already has answers here:
In Typescript, what is the ! (exclamation mark / bang) operator when dereferencing a member?
(5 answers)
Closed 3 years ago.
I've been seeing this creep up in a few places now but have not found any answers on it.
I'm curious what the '!' bang does in the angular syntax.
From the Angular documentation:
The non-null assertion operator ( ! )
As of Typescript 2.0, you can enforce strict null checking with the
--strictNullChecks flag. TypeScript then ensures that no variable is unintentionally null or undefined.
In this mode, typed variables disallow null and undefined by default.
The type checker throws an error if you leave a variable unassigned or
try to assign null or undefined to a variable whose type disallows
null and undefined.
The type checker also throws an error if it can't determine whether a
variable will be null or undefined at runtime. You may know that can't
happen but the type checker doesn't know. You tell the type checker
that it can't happen by applying the post-fix non-null assertion
operator (!).
The Angular non-null assertion operator (!) serves the same purpose in
an Angular template.
For example, after you use *ngIf to check that hero is defined, you
can assert that hero properties are also defined.
<!-- No hero, no text -->
<div *ngIf="hero">
The hero's name is {{hero!.name}}
</div>
When the Angular compiler turns your template into TypeScript code, it
prevents TypeScript from reporting that hero.name might be null or
undefined.
Unlike the safe navigation operator, the non-null assertion operator
does not guard against null or undefined. Rather it tells the
TypeScript type checker to suspend strict null checks for a specific
property expression.
You'll need this template operator when you turn on strict null
checks. It's optional otherwise.
Its called the "Non-null assertion operator" and has nothing todo with Angular perse, it is from typescript.
let s = e!.name; // Assert that e is non-null and access name

variable with interrogation point at the end [duplicate]

I've seen code snippets like these:
export interface IUser {
email?: string;
firstName?: string;
lastName?: string;
}
But why are the variable names suffixed by a question mark? This snippet is part of an example of using mongodb with Typescript.
The answer is probably somewhere out there but I seem to be using the wrong keywords since I can't find it.
In TypeScript, <name>?: <typename> a shorthand for <name>: <typename> | undefined.
This indicates to the type system that a symbol may contain a value of the indicated type or it may contain the value undefined (which is like null).
This is important when the (new in TypeScript 2) --strictNullChecks option is enabled. The documentation on Null- and undefined-aware types option is probably where you should start to understand why this is useful.
It means they can be there but dont have to be. It allows for optional field names. It can be quite common to use.
An example use is allowing users on a website to have an optional display name.
If I am not mistaked, its to indicate that its optional, that means that it can be null.

How do we know when to call "value" as opposed to "value()"?

Have a look at the last two answers.
How can we determine without looking into any documentation that sliderinput.value is the right answer, and not sliderinput.value()?
Im coming from Java. Im used to call accessor methods.
What is "value" as opposed to "value()"?
What is sliderinput if not an object?
You can determine this by checking if value is a function:
typeof sliderinput.value === "function"
Javascript usually doesn't use getter functions like value(). If you want to use getters you can use the get syntax to create a getter function that can be called using normal property syntax. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
In the context of this quiz you've posted, I suppose they just want you to know from the top of your head that value is a property in this case.
How can we determine without looking into any documentation that sliderinput.value is the right answer, and not sliderinput.value()?
You can try it and see.
You can test its type (with the typeof operator) to see if it is a function or something else.
… but reading the documentation, despite you dismissing it, is the correct approach.
Note that the attribute value of sliderinput is a string, so the options with parenthesis () are not valid and will throw an error. You could do that only if value were a function type variable, which is not.
Edit: as other members pointed out, you can use typeof to check the variable type; in this case it will be "string"

Why does assigning to `NaN` or `undefined` cause a TypeError?

A.S.: The question is about type of error, not about the phenomenon
"use strict" throws TypeError if system variables like NaN and undefined got changed.
But why is it a TypeError? Why not SyntaxError?
Edit: Really, it is not the SyntaxError here since there are no errors in syntax of the snippet.
But the root of the error lies in the fact, that some protected object cannot be changed manually; so, it is lkely the AccessError (there are no such, I know).
Then, why access-errors appear like type-ones?
In ES5, there are 6 different kinds of native errors:
EvalError
This exception is not currently used within this specification. This
object remains for compatibility with previous editions of this
specification.
RangeError
Indicates a numeric value has exceeded the allowable range.
ReferenceError
Indicate that an invalid reference value has been detected.
SyntaxError
Indicates that a parsing error has occurred.
TypeError
Indicates the actual type of an operand is different than the expected
type.
URIError
Indicates that one of the global URI handling functions was used in a
way that is incompatible with its definition.
In your case, the error is thrown because you attempt to assign a value to window.NaN or window.undefined, which are non-writable properties.
Before assigning the new value, the internal [[Put]] method checks [[CanPut]], which will return false because the property is non-enumerable. And therefore [[Put]] will throw.
So the problem is that the writability of the assigned reference (left operand in the assignment expression) is not the expected one. Then, among the 6 error kinds above, the most appropriate seems TypeError, even if writability is not exactly a type.
Because NaN and undefined are just read only properties of window. They are not operators (like > or +), or keywords (like var or class).
Trying to assign something to NaN gives the following error in Chrome:
TypeError: Cannot assign to read only property 'NaN' of object '#<Window>'
Because it's a valid argument that does not make sense. But it does not make sense in the SEMANTIC level, not the syntactic.
Here's an example:
1+1=42
This is wrong, but it's wrong in a different way than, say:
42 1 1 + =
You can read the first one as an arithmetic equation (one plus one equals forty-two). The second one, you can't even read.
The same goes here. the statement NaN=300; can be read in Javascript as "have NaN point to the value 300`. But when the parser submit this request to the engine, the engine goes "Nope, can't do this".
syntax error
In most programming & scripting languages this generally means that you've used an operator in the wrong place.
For more info on "syntax errors", have a look at this article: https://en.wikipedia.org/wiki/Syntax_error
type error
These occur when a data-type miss-matches some requirement.
For more information on "data-types", have a look at this article: https://en.wikipedia.org/wiki/Data_type
So, the type error is thrown because NaN and undefined are "data-types", which are global constants with a specific (designated) value, and "strict mode" prevents issues by not allowing to change these.

How does Javascript handle function parameters

I recently had an issue with some javascript that goes against every bone of my programming background. Javascript does this often to me, so I'm not that surprised.
I have a function as such...
function x(param1, booleanParam, arrayParam){
....
}
I was getting a runtime error saying that arrayParam.length was not defined. On debugging I saw this was true and went to find out why. Turns out I had forgotten a comma in my function call as such...
x(param1, true [arrayJunk]);
The problem I'm having is figuring out why this call was made at all? Why isn't this a compile error, how does Javascript see this and think, "Yeah, that seems like it might work!"
Thanks in advance for any enlightenment you can share!
That's an indexing expression.
It's the same syntax as someArray[someIndex].
It will end up passing undefined as the second parameter too, unless arrayJunk happens to be the name of a property of boolean primitives.
What happens is the following:
JavaScript engine converts true into a Boolean object (not the primitive)
It then tries to access the property name stored in arrayParam from that object
Property doesn't exist, so it returns undefined
If arrayParam was the string "toString", it would return a function object
In this case the expression was being interpreted as an index. Essentially the same as
someArray[42]
So it was being seen as a function call with 2 parameters instead of 3
Many dynamic languages don't check if you pass too many or too few arguments to a function.
While this can sometimes mask errors, it also allows you to roll your own defalut parameter scheme.

Categories

Resources