Monday, February 12, 2018

If it looks like a lobster and celebrates Mardi Gras three days early we're going to call it a lobster.

I took the photo here at Mardi Gras festivities being celebrated in St. Louis two days ago on a Saturday even though Fat Tuesday doesn't come until tomorrow. Do not let the strangeness of when be a distraction though. I'd like you to instead focus on the strangeness here that would test Barbara Liskov's patience. I went through a training at work today on TypeScript and Angular 4 and that made me think of the Lobster woman I saw this weekend. A different definition than the one Kyle Simpson gives here comes in lose-with-the-rules TypeScript wherein it is possible say: "If it looks like a duck and quacks like a duck we're going to call it a duck." Let me explain the shape of that. It is possible to have a class inherit from (er, implement) an interface as it might in C#. That's not what I mean. It is also possible to declare a variable with let myVariableName colon myInterfaceName equals and then break into curly braces to toss together a JSON object that must also satisfy the criteria of the interface and that is also not what I mean. What I mean is that when a method signature requires an interface that you may just hand in anything that satisfies the requirements. It can be a class that does not implement the interface but happens to do what the interface does. So what else did I learn today? There are tagged templates and mixins in TypeScript which I don't yet understand. I do get index files for Angular apps. At any one folder you may have an index.ts file and it will hold nothing but import statements. You may then import all of the imports as one import in other TypeScript files. The index files may also loop in other index files in other folders too. An index file is sometimes referred to as a "barrel" and you may import lots and lots of classes from an index.ts file or you may less traditionally use an import star (asterisk) as myAlias approach and then do myAlias.Whatever downstream in code to get at the various types at myAlias! If a parent class has a constructor an inheriting child has to have super(); at its constructor. There will be a compilation error otherwise. The dot dot dot operation that looks like ... is the spread operator in some cases but it is the rest operator when used with the last variable of a function. You lead the name of the last variable with ... and you make the last variable an array of any. Then all of the variables that you declare beyond the variables before the variable with the rest operator, and you may have any number of them, will end up in the array of any. The let and const keywords are block-scoped as I've eluded to before and const does not allow for reassignment. The different between readonly and const is that readonly appears at a property at a class or an interface while const is just for a variable. The following is an example of unpacking variables that I may have given before:

let meh = { foo: 13, bar: 42, baz: 69, qux: 86 };
let { foo, bar } = meh;
console.log(foo);
console.log(bar);

 
 

This gives back 13 and 42! In lieu of console.log, console.dir can give you some extra stuff and a bigger breakdown of an object. It may be more expansive for DOM objects. Having manipulation="dog" in lieu of [manipulation]="dog" at a component's selector tag is going to pass to the component a string variable named manipulation with "dog" inside instead of handing the dog object on to the manipulation Input. If you planned to have Sarah McLachlan sing while you showed pictures of sad dogs this could get in the way so be wary. There is a way to make string restrictions for a string kinda in the shape of a custom type like so:

let meh: "shrug" | "sigh" | "yawn" = "yawn";

 
 

It is possible to make your own custom decorators. ViewEncapsulation as a setting determines if you have to use the ::ng-deep hack to style a component nested in the one you are immediately affecting with a stylesheet and it might be wise to make your developers jump through such hoops honestly. The stylesheets should probably be component specific and contained most of the time. There is a distinction between number enums and string enums as suggested by Stack Overflow here like so:

enum e {
   hello = 1,
   world = 2
};
enum E {
   hello = "hello",
   world = "world"
};

 
 

There will never be compilation errors with type assertions (think casting in C#) because in the underlying JavaScript there is no compiler sanity checking around types. There are some interesting quirks with arrow functions. This gives us undefined:

let yinYang = {
   yin: "yawn",
   yang: () => console.log(this.yin)
};
yinYang.yang();

 
 

This actually puts "yawn" to the console though:

let yinYang = {
   yin: "yawn",
   yang: function() { console.log(this.yin); }
};
yinYang.yang();

 
 

This won't work, again giving undefined.

let yinYang = {
   yin: "yawn",
   yang: () => {
      shrug: "sigh"
   }
};
console.log(yinYang.yang());

 
 

This is the fix:

let yinYang = {
   yin: "yawn",
   yang: () => ({
      shrug: "sigh"
   })
};
console.log(yinYang.yang());

 
 

Note the return keyword is absent from the fat arrow function. It is sort of implicitly implied. An attribute directive starting out like so:

@Directive({
   selector: '[parrot]'
}
export class ParrotDirective {
   constructor() {}
   squawk: string;

 
 

May take a confusing shape in markup like so:

<div parrot [squawk]="Polly wants a cracker!"></div>

 
 

A revamp like this:

@Directive({
   selector: '[parrot]'
}
export class ParrotDirective {
   constructor() {}
   @Input("parrot") squawk: string;

 
 

Allows for this:

<div [parrot]="Polly wants a cracker!"></div>

 
 

ngAfterViewInit is the lifecycle hook for getting at ViewChild variables and components within the component. ngDoCheck is for detecting and acting on changes that Angular won't act on on its own. Even my superior giving the training wasn't sure what this thing did, but felt it smelled like something to avoid. useExisting, useValue, and useFactory are other things like useClass that you may use in the dependency injection. useValue behaves like a singleton and useFactory opens the door to a fine level of control into how injection works. You probably don't want to go there either though. Putting @Optional() before a variable or perhaps the public or private keyword before a variable at the signature of a constructor when looping in an injected service keeps the application from breaking if the service isn't hydrated.

 
 

Addendum 2/13/2018: One way to not call a parent's constructor from a child's constructor is to just not have a constructor at the child. You can get away with that. While this is legit:

class Cat {
   saying: string;
   constructor() {
      this.saying = "meow";
   }
   speak(): void {
      alert(this.saying);
   }
}
class Tiger extends Cat {
   constructor() {
      super();
      this.saying = "ROAR";
   }
}
let tiger: Tiger = new Tiger();
tiger.speak();

 
 

...this too is also legit:

class Cat {
   saying: string;
   constructor() {
      this.saying = "meow";
   }
   speak(): void {
      alert(this.saying);
   }
}
class Tiger extends Cat {
}
let tiger: Tiger = new Tiger();
tiger.speak();

 
 

Hey! It's finally Fat Tuesday!

No comments:

Post a Comment