Two Important Rules - ldco2016/microurb_web_framework GitHub Wiki

So I need to do some major work on the get() method below:

export class Attributes<T> {
  constructor(private data: T) {}

  get(propName: string): number | string | boolean {
    return this.data[propName];
  }

  set(update: T): void {
    Object.assign(this.data, update);
  }
}

I need to fix this and make it look really nice using generics, but before I do that I want to document two important topics.

Two Important Topics

  1. In TypeScript, strings can be types
  • I will write out some code below to explore this idea. I will going to create a tuple with a type alias.

type MatchData = [string, number, number];

  • I can use this type alias syntax to create other new types using other values besides an array. So I can use this type alias syntax to create a type of string as well.
  • To do so I can write out the following:

type BestName = 'daniel';

  • I am not creating a variable declaration here, this is actually creating a type. I can use the word BestName in any location where I would normally put a type annotation, for example, a function call like so:
type BestName = 'daniel';

const printName = () => {};
  • I will say that the only possible value that you can send to this function is a type of BestName like so:
type BestName = 'daniel';

const printName = (name: BestName): void => {};
  • So when we normally build out a function like this and put in a type of string like so, const printName = (name: string): void => {};, that means I can pass in any string that I want whatsoever, but by putting BestName with BestName being its type, it will only call printName with a string of 'daniel'.

If I try to call printName with any other string:

type BestName = 'daniel';

const printName = (name: BestName): void => {};

printName('asdf');
  • I get an error, its not allowed because this string above is not of type 'daniel', that's essentially what we are looking at there.

  • So the only value I can call printName() with is the name with a value of type BestName and for a value to be of type BestName, it must be a string and it must have the characters 'daniel' like so:

type BestName = 'daniel';

const printName = (name: BestName): void => {};

printName('asdf');
printName('daniel');
  • The second call succeeds, but the first one fails.

  • It turns out there are a lot of scenarios where we might want to create a type out of a string. In Redux, it turns out that being able to type your actions, it turns out that this feature works nice with Redux.

  • So a string can be a type.

  1. In JavaScript (and therefore TypeScript), all object keys are strings
  • For this I will demonstrate it in my Chrome browser console. I am going to create an object called colors like so, const colors = {};. I want to add a property to this thing and I want the property to be red like so:
colors.red = 'red';
"red"
  • If I print out colors I get:
colors
{red: "red"}
  • I will now try doing the same with with a number. I will use the number as a key, to do so in JavaScript I have to use that square bracket syntax like so, colors[5] = 'red';.
  • So now it would appear that I am using a number as a key. If I hit that and print out colors again I can see the key:
colors[5] = 'red';
"red"
colors
{5: "red", red: "red"}
  • Even though it looks like to me that the number 5 is a key and I can actually even verify that like so:
colors[5]
"red"
  • That makes me think that the key is a number, but thats not really whats going on behind the scenes. Whenever you use a number like this, behind the scenes, JavaScript takes that number and first turns it into a string and that happens anytime you try to access a property or set a property on an object. So in reality, even though I think I am using a number as a key, its really a string and I can prove it:
colors['5']
"red"
  • So I still get back "red". So even though I really see a number as a key, internally it is first being converted to a string and then that string is being added to the object as a property.

So what is the impact of:

  1. In TypeScript, strings can be types
  2. In JavaScript (and therefore TypeScript), all object keys are strings

What do these two facts together tell us? Well, it tells me that on an object or the keys of an object can actually be a type as well.