A Typescript syntax clarification - javascript

I am reading a code written in Typescript. I'm not sure if I understand it correctly:
export class MyClass<B> {
value: B;
constructor(value: B) {
this.value = value;
}
isMyClass(): this is MyClass<B> {
return true;
}
}
What does the <B> stand for? What does it represent, a Type? If so, what Type is it?
What is this is MyClass<B> in isMyClass(): this is MyClass<B>? Is it being evaluated for true or false? Why not to put this inside of the function itself then, something like this:
isMyClass() {
if (this is MyClass) {
return true;
}
else {
return false;
}
}
And I am not able to find the answer to a these questions.

What does the <B> stand for? What does it represent, a Type? If so, what Type is it?
That's a type parameter, also known as generics. See the TS handbook.
In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is generics, that is, being able to create a component that can work over a variety of types rather than a single one. This allows users to consume these components and use their own types.
Whenever one calls a function or creates an instance, if the function or class is generic, you can "pass" a type parameter to it, similar to how arguments can be passed to a function or constructor. (The difference is that the type parameter, being a type, doesn't exist in the emitted JS - it's just there to help TS type-check).
If so, what Type is it?
It's whatever type the constructor parameter is called with.
const m = new MyClass(3);
will result in
constructor(value: B)
where value is 3, telling TypeScript that the resulting instance is a MyClass<number> - in other words, that its value property holds a number, a B.
What is this is MyClass<B> in isMyClass(): this is MyClass<B>? Is it being evaluated for true or false? Why not to put this inside of the function itself then, something like this:
The
isMyClass(): this is MyClass<B> {
is a type guard. If the method returns true, it tells TypeScript that the instance is of type MyClass<B>.
While you could do something like:
isMyClass() {
if (this instanceof MyClass) {
return true;
}
else {
return false;
}
}
That wouldn't allow TypeScript to understand that the type has been narrowed when isMyClass is called; it'll just return a boolean. In contrast, using the is will both return a Boolean and give TypeScript type information about what was called.

Related

Typescript generics and returning functions

I have a function that accepts another function as an argument, and returns a function having the same input type signature, but void instead of whatever output type the inner function had. The actual code does some other things, but here's the dumbed down version of it. I just can't seem to get the types right. Here's what I have so far (I'm aware it's wrong):
export function foo<Type>(func : (_ : Type) => any) {
return function bar(...args : Type) : void {
func.apply(null, args)
}
}
The first line doesn't really capture what I want it to - the entire argument list of func should be Type, not just the first argument. I can't seem to be able to do so, though. (Note that Type[] doesn't capture the intended use, since not all arguments need to be the same type.) Is this even possible given the generics that Typescript offers?

specify the result of a function in javascript

Am not sure if functions in javascript are what we call methods in other programming languages.Methods in other programming languages can have their result specified just after the access-specifier like in C# for example i would do like
//method to return int
private int myinteger(){
int a=0;
return a;
}
//method to return string
private string mystring(){
string b="myreturn";
return b;
}
I just don't know how to do that with javascript functions, you think you can help me with a sample?Thank You very much :)
You don't need to provide the data types in javascript. The functions are pretty similar you just have to start it with the function keyword.
Also, we need to start the variables with const or let.
I use the console.log(myinteger()); below to log the value of the myinteger() function in the browser console. (Similar to c++'s cout)
//method to return int
function myinteger() {
const a = 0;
return a;
}
//method to return string
function mystring() {
const b = "myreturn";
return b;
}
console.log(myinteger());
console.log(mystring());
If you are someone who wants to use javascript but still want to assign the data type and many more thing then you can use TypeScript By Microsoft.
You cannot do this with javascript, but you still have two workarounds available:
Use eslint and use the https://eslint.org/docs/rules/consistent-return rule
Use typescript
Javascript has types for values (not variables)
so you can define a variable as
var name = "Hamond";
and to know it's type you have to use typeof
typeof name; // "string"
Side note: you can use let or const instead of var but let that be for another time.
so variables in javascript doesn't have types, values have.
You can add static typing using typescript so
var name: string = "Hamond";
and at dev time if you wanted to edit name and incorrectly deal with it as a non string type you will get an error
warning you immediately
name = 3; // error
name - 4; // error
// and so forth because `name` is of `string` type
so this type check is done at author or dev time and you don't have to wait until run time to get the error.
Why all the talk about variables and values?
Because Javascript function can return any value(even returning a variable is basically returning its value if it's scalar value or its reference if it's an object type)
so defining a function look like:
function doSomething(){
return 33;
}
notes:
no return type
can have no return statement(by default will return undefined)
with typescript
function doSomething(): number{
return 33;
}
typing problems solved at dev/write time
About function vs method:
I think developers in many times use these terms interchangeably, but in javascript we just have function, even a function defined inside a class in javascript is just a function. People like the name method when its defined inside some class.
references:
JS syntax
The Nature Of Functions

Confused about Javascript. A boolean function can act as a void function?

I'm trying to refresh some Javascript knowledge for an upcoming interview. I was reading a blog that says
"The delete operator returns true if the delete was successful."
and then shows an example of it in use:
var christmasList = {mike:"Book", jason:"sweater" }
​delete christmasList.mike; // deletes the mike property​
In that example it looks like delete is used in the manner that a void function (in the general programming sense -- I know that JS doesn't require declarations like void) would be.
Can someone explain to me, or give me a link to, the documentation that explains how JS functions can act with different return values, and does such require separate implementations for each return value?
You can check the Delete operator which says:
If desc.[[Configurable]] is true, then
Remove the own property with name P from O.
Return true.
Note that delete only works for properties of objects. Also a good read:- JavaScript Delete() Only Affects The Referenced Object Regardless Of Prototype Chain
In that example it looks like delete is used in the manner that a void function
The delete operator is not a function, it is an operator. It deals with properties of objects, not their values.
Functions are something else, but since you asked:
Can someone explain to me how JS functions can act with different return values
JavaScript is loosely typed. Functions don't care about the types of values unless they need to, and (most of the time) conversion between types is handled by operators.
If a function needs to are about what it is operating on, then it has to examine the value to see what it is.
For example:
function myFunction(myArgument) {
if (typeof myArgument === "function") {
return myArgument();
} else {
return myArgument;
}
}
A function can return any value it likes.
function string_or_number() {
if (Math.random() > 0.5) {
return 1;
} else {
return "1";
}
}
Strongly typed languages care about what type of value a function returns and what type of value is passed into an argument.
Loosely typed ones simply don't. There's nothing special about it from the point of view of someone using the language.
It shunts most of the complexity about having to care about types to the compiler author instead of the user of the compiler (who just has to care that, if a function is designed to do something to a duck, what they pass is sufficiently like a duck to not break the function).
As others note, delete is technically an operator and not a function; for our immediate concerns, however, the difference is academic, as the operator's behavior is the same as that of many functions used for their side effects (which is to say, void functions). Both the rule of the language and the conventions of their use are simple.
Rule
All functions provide a return value; if no return statement is reached, this will be undefined
Conventions
Since we always get a return value, we can take advantage of it to improve our programs. There are two conventions; which one should be used depends on the use case.
Return a boolean, signalling success or failure
Return some object being operated on
Option 2 is most useful for methods on objects: if our method changes the state of the object and then returns the object, we can bundle several changes into a single line of method calls: object.change1().change2().change3(newVal);
Option 1 is most useful when we want to use the success or failure of an operation to determine program flow; maybe we want to throw an exception if the property was not deleted but continue normally if it was. Then we can use if (delete object.property) to attempt to delete the property and branch into success/failure cases immediately.
From the MDN on the delete operator:
Throws in strict mode if the property is an own non-configurable property (returns false in non-strict). Returns true in all other cases.
I can't make it simpler than that. Aside from a small example:
alert(delete window.window)
alert(delete window.foobar)
alert(delete window.alert)
Javascript functions always return ambigious values. One function can return boolean, string, object, array or HTMLElement.
There is no fixed type.
function masterSwitch(input) {
switch(input) {
case 0 : return "Hello";
case 1 : return 0xdead;
case 2 : return 0.00042;
case 3 : return document.createElement("DIV");
case 4 : return true;
case 5 : return window;
case 6 : return this;
case 7 : return null;
default:window.alert("Please specify input from 0 to 8");
}
}
<input type="text" id="output"> <SELECT onchange="document.getElementById('output').value = typeof masterSwitch(this.selectedIndex);">
<option>string</option>
<option>int</option>
<option>float</option>
<option>HTMLElement</option>
<option>boolean</option>
<option>window</option>
<option>this</option>
<option>null</option>
</select>

Is there a way I can check a function parameter has an allowed value before runtime with Typescript?

I have an AngularJS service coded in Typescript. I call the functions of the service with a parameter like this setFalse('retrieve'):
class StateService implements IStateService {
state = [];
get = (property: string) => {
return this.state[property];
}
setFalse = (property: string) => {
this.state[property] = false;
}
setNull = (property: string) => {
this.state[property] = null;
}
setTrue = (property: string) => {
this.state[property] = true;
}
// more code here
}
Is there some way that I could remove the need for the quoted string 'retrieve', use a constant or check the values being used before run time?
1. Is there some way that I could remove the need for the quoted string 'retrieve'?
You could desugar the overload, and provide lots of different versions of the function.
//just to give the idea
function setFalse_retrieve(){ return setFalse('retrieve') }
The upside of doing this is that its really typesafe and there is no way to ever call setFalse with a bad parameter. The downside is that there is lots of boilerplate and you can't pass around a property value if you want to.
2. Use a constant?
Typescript has an enum feature for this:
enum Properties { retrieve, frobnicate };
You can now use Properties.retrieve instead of "retrieve" in your code and it will catch any typos in the enum name.
Properties.retriev; // Error: The property 'retriev' does not exist on value of type 'typeof Properties'.
Just be aware that Typescript makes the enum values be integers so you will need to convert them to strings when calling the Angular functions:
var enumProperty = Properties.retrieve; // 0
var strProperty = Properties[enumProperty]; // "retrieve"
The downside of the enum approach is that you can pass any number where an enum value is expected and the error will not be detected at runtime (do don't do that):
var x:Property = 10; // :(
3. Use a constant or check the values being used before run time
Typescript has function overloading on function constants but AFAIK, you can only use it to specialize return types depending on inputs, not to restrict your valid inputs to a set of constants. That is, you would still need to have a generic case that accepts any string, which is not what you want.

Check to see if function call has correct argument types

Is there a way to check whether a function call has the correct argument types.
Let's say I have a function called changeCar which takes two arguments one of type Car and another of type String.
function Car(){
this.make="generic";
}
function changeCar(car,mytype){
car.make=mytype;
}
var mycar=new Car();
changeCar(mycar,"ferrari");
Is there anyway to tell whether mycar and "ferrari" are the correct types needed to run changeCar?
I need to do this before the script is run if possible maybe using eval or try/catch to look for mistakes.
The application allows students to type in a javascript scripts and looks for errors in the function arguments and function calls.
function changeCar (car, mytype) {
if ( car instanceof Car && mytype.toLowerCase ) {
car.make = mytype;
}
}
Duck typing FTW.

Categories