Monday, July 31, 2017

Redux combineReducers compiler error

If a Redux action is added with properties other than the type property, here it's payload..

export interface UserActions extends Action {
    type: UserKind;
    payload: UserPayload;
}

..TypeScript will raise an error on combineReducers:



To fix the compilation error, make the Redux action property be optional:

export interface UserActions extends Action {
    type: UserKind;
    payload?: UserPayload;
}


Result:




However, TypeScript won't be able to catch missed properties, it won't raise an error that we didn't pass the payload property on User 6:




To fix that, remove the optional indicator on Redux action:

export interface UserActions extends Action {
    type: UserKind;
    payload: UserPayload;
}


Result, TypeScript is now able to catch missed properties:




However, we are back to this error on combineReducers:




To comply with combineReducers requirement of Reducer actions containing just a type property only, create another interface that has optional properties (e.g., payload), and use that for the Redux reducer's action parameter (UserActionsNoPayload). And then on UserActions, inherit UserActionsNoPayload from UserActions:



Now, no more combineReducers compilation error, and the compiler is still able to catch missed properties:




Here are the TypeScript definitions for the routeToUser:

export interface StateProps {
    user: Dto.Client.User;
    component: Component;
    counter: Dto.Client.Counter;
}


export interface ActionProps {
    routeToUser: UserDispatcher;
    doCounter: CounterDispatcher;
}


interface Props extends StateProps, ActionProps {
}


export type Dispatcher = (action: UserActions | CounterActions) => void;
export type UserDispatcher = (action: UserActions) => void;
export type CounterDispatcher = (action: CounterActions) => void;


export default class ReduxFirstRouterApp extends React.Component<Props, {}> {



And here is how are the states and dispatchers are mapped as properties to a component via Redux's connect:
const mapStateToProps = ({user, component, counter}: StateProps) => ({user, component, counter});

const mapDispatchToProps = (dispatch: Dispatcher): ActionProps => ({
    routeToUser: (action: UserActions) => dispatch(action),
    doCounter: (action: CounterActions) => dispatch(action)
});

this.AppContainer = connect(mapStateToProps, mapDispatchToProps)(ReduxFirstRouterApp);


Happy Coding!


P.S.

At first, I tried creating UserActions with complete properties, and then made UserActionsNoPayload inherits UserActions and define payload as optional on UserActionsNoPayload; however, it's a compiler error:


Sunday, July 23, 2017

Inline destructuring

Found out a neat ES6 functionality, it can do destructuring of object right on parameters itself.

Below is how it is done on TypeScript:

function greetNoDestructuring(dto: {name: string, favoriteNumber: number}): void {    
    console.log(dto.name);
    console.log(dto.favoriteNumber);
}

function greetManualDestructuring(dto: {name: string, favoriteNumber: number}): void {
    const {name, favoriteNumber} = dto;

    console.log(name);
    console.log(favoriteNumber);
}

function greetInlineDestructuring({name, favoriteNumber}: {name: string, favoriteNumber: number}): void {
    console.log(name);
    console.log(favoriteNumber);
}


greetNoDestructuring({name: 'Kal', favoriteNumber: 7});
greetManualDestructuring({name: 'El', favoriteNumber: 6});
greetInlineDestructuring({name: 'Superman', favoriteNumber: 42});


Happy Coding!

redux-first-router 404



As with all client-side routing, when page is reloaded it will result to 404.

The easiest way to fix that is to indicate fallback page when 404 occurs, this is typically the index.html

On development environment that are using webpack-dev-server, just add the following:

devServer: {
    hot: true,
    proxy: {
        "/api": "http://localhost:3000"
    },
    historyApiFallback: {
        index: "/index.html"
    }
}


Aside from the above, on the fallback page indicate the base href:

<base href="/"/>



Happy Coding!

TypeScript + redux-first-router expected string class/function

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of `App`

When that runtime error occurred, chances is the default is forgotten when importing Link since there is no TypeScript definition for redux-first-router-link yet.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Provider, connect } from 'react-redux';
const Link = require('redux-first-router-link');

To fix:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Provider, connect } from 'react-redux';
const Link = require('redux-first-router-link').default;


Happy coding!

Thursday, July 20, 2017

TypeScript can enforce code correctness is so awesome

Following is a compile-time error:



To correct that, use 'onClick' not 'onclick':




Checked the TypeScript definition of prop function:




Don't know yet how extends keyof works. One thing for sure, it truly helps developers avoid mistakes.


Happy Coding!

TypeScript solves the industry's billion dollar mistake too

Reading about the advantage of Flow over TypeScript. Saw these slides:



With Flow, the error is caught at compile-time instead, which indeeds solves the billion dollar mistake:



TypeScript 2.0 already has the same functionality as Flow, it's just not the default. Just add "strictNullChecks": true to tsconfig.json.



With that settings, possible null/undefined errors can now be caught at compile-time:



If the type is explicitly added to the function it will complain that there is a path that could lead to undefined value:



Just include the undefined value in function's return type:



The inferred return type for function foo if return type is not included is string | undefined

Finally, to fix the undefined error:



Of course, if it can be guaranteed that a function returns a non-null/non-undefined value, no need to add undefined:




Happy Coding!



Wednesday, June 14, 2017

GPG failed to write commit object

Got an error:

error: gpg failed to sign the data fatal: failed to write commit object


It took me more than two hours to narrow down the cause of the error:

These does not work too:
MacBook-Air:~ jack$ gpg2 --list-secret-keys
gpg: can't connect to the agent: IPC connect call failed
MacBook-Air:~ jack$ gpg-agent --daemon
gpg-agent[1499]: /Users/jack/.gnupg/gpg-agent.conf:2: invalid option

Error is caused by wrong configuration in gpg-agent.conf:

$ cat ~/.gnupg/gpg-agent.conf 


For some reasons the second line was added to the configuration:
pinentry-program /usr/local/bin/pinentry-mac 
/usr/local/bin/pinentry-mac 


That should just configured with this:
pinentry-program /usr/local/bin/pinentry-mac 

After correcting the configuration, gpg-agent is now working:

MacBook-Air:~ jack$ gpg-agent -v --daemon
gpg-agent[2012]: listening on socket '/Users/jack/.gnupg/S.gpg-agent'
gpg-agent[2012]: listening on socket '/Users/jack/.gnupg/S.gpg-agent.extra'
gpg-agent[2012]: listening on socket '/Users/jack/.gnupg/S.gpg-agent.browser'
gpg-agent[2012]: listening on socket '/Users/jack/.gnupg/S.gpg-agent.ssh'
gpg-agent[2013]: gpg-agent (GnuPG) 2.1.21 started

And so is gpg2:
MacBook-Air:~ jack$ gpg2 --list-secret-keys
gpg-agent[2013]: handler 0x70000e9d4000 for fd 7 started
/Users/jack/.gnupg/pubring.gpg
------------------------------
sec   rsa2048 2016-12-12 [SC]


With that, committing with gpg signing shall work, must configure gpg to use gpg2 if it is not yet configured to gpg2:
MacBook-Air:~ jack$ git config --global gpg.program gpg2


Happy Coding!

Monday, April 10, 2017

Tuples in TypeScript/ES6 and C# 7

TypeScript and ES6 has tuple functionality:




C# tuple is more flexible, as aside from that it allows destructuring the tuple to variables, it also supports returning the object as-is:




The named tuple can be easily achieved in TypeScript/ES6 by returning an object instead of array, however, the destructuring to variables using the array syntax won't work anymore:



Would have to use object destructuring syntax:




However, unlike in C#, that won't work in TypeScript/ES6. In TypeScript/ES6, we would have to match the name of the variables to the name of the object's property names that is being destructured from.




But if you really don't like the object's property names given by the author of the function, or it conflicts with your existing variable name; with TypeScript/ES6, you can rename the destructured variable using the following syntax:




Read more:

https://blogs.msdn.microsoft.com/typescript/2014/11/12/announcing-typescript-1-3/

https://strongloop.com/strongblog/getting-started-with-javascript-es6-destructuring/

http://wesbos.com/destructuring-renaming/

http://blog.marcgravell.com/2017/04/exploring-tuples-as-library-author.html


Happy Coding!

Tuesday, January 17, 2017

404 not found.

Got the error "Failed to decode downloaded font OTS parsing error: invalid version tag" and looks like the font can be read/decoded by the browser as the font can be previewed in the browser:





Making it seems that the reason why TinyMCE is not loading the fonts correctly..




..is due to incorrect mime type of text/html:




Although the font can be previewed by the browser, it looks like it is from previous successfully loaded font. Meaning, the browser aggressively caches the fonts, making it look like there is a very serious error, e.g., incorrect mime type of text/html when it should be application/woff, when in reality it is just a 404 that resulted to a 404 page(seemingly), yet without the status code of 404. A page is text/html.


The docker built just don't have font files in it.


Suggestions like nginx has missing mime types for the fonts, made the error looks complex than it really is.


404s are mostly a page, so that might be reason for the content type of text/html being reported by the browser. The browser might be returning a page, but it's hard to actually know since what the browser previews is the actual font, not a page. As for why the app is not returning status code of 404, would have to find out.



Happy Coding!

nginx proxy https node express


server {
    listen 443 ssl;

    server_name domain.name.here.com;

    ssl_certificate /usr/local/etc/nginx/cert.crt;
    ssl_certificate_key /usr/local/etc/nginx/cert.key;

    location / {
        proxy_pass https://127.0.0.1:3000;
        proxy_set_header host $host;

        # proxy_connect_timeout       600;
        # proxy_send_timeout          600;
        # proxy_read_timeout          600;
        # send_timeout                600;
   }
}

To create a certificate in homebrew'd nginx:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /usr/local/etc/nginx/cert.key -out /usr/local/etc/nginx/cert.crt

Friday, January 13, 2017

Protobufjs unresolvable field type

If you got this error, one cause is there are many roots. Even if ecommerce.proto below imports the common.proto, protobufjs won't be able to resolve the message type if they are in different roots.

Instead of:

const common    = protobufjs.loadSync('common.proto');
const ecommerce = protobufjs.loadSync('ecommerce.proto');
const hr        = protobufjs.loadSync('hr.proto');


One solution:
const common = protobufjs.loadSync('common.proto');
protobufjs.loadSync('ecommerce.proto', common);
protobufjs.loadSync('hr.proto', common);

Another solution:
const root = protobufjs.loadSync([
    'common.proto', 
    'ecommerce.proto', 
    'hr.proto'
]);


Happy Coding!

Thursday, January 12, 2017

TypeScript + enum + node that works

If you have an internal module in TypeScript and use it on node, and wanted to add an enum on it:

task.ts:
module com.anicehumble
{
   export enum Status 
   {
       PENDING = 0,
       IN_PROGRESS = 1,
       COMPLETED = 2
   }
   
   export interface Task
   {
       uuid: com.anicehumble.uuid;
       ownedBy: string;
       title: string;
       status: Status;
   }
}


Then the reading the value of enum would result to runtime error: 'com is not defined':
console.log(com.anicehumble.Status.IN_PROGRESS);


If we try to move the enum Status and make it node-compatible by putting it on separate file without the module namespace and exporting the enum, the task.ts will be interpreted as external module instead, and as such, all dotted names will be interpreted as external modules too and would result to compile-time error if they are not imported, e.g., TypeScript will complain that it has no exported member uuid on com.anicehumble even there is one defined on an internal module, as all names under com.anicehumble will now be interpreted as external modules instead.

When a module become an external one like the code below, all members (e.g., uuid) under the module com.anicehumble should be moved to task.ts and cannot be defined anymore in an internal module on a separate file; or if it will not be inlined in task.ts, uuid should be implemented as external module, and it should be imported like the importing of Enums from the-enums.ts below:


the-enums.ts:
export enum Status
{
    PENDING     = 0,
    IN_PROGRESS = 1,
    COMPLETED   = 2
}


task.ts:
import * as Enums from './the-enums';

module com.anicehumble
{   
   export interface Task
   {
       uuid: com.anicehumble.uuid; // TypeScript will complain com.anicehumble 'has no exported member uuid' even it is defined in an internal module on a separate file.
       ownedBy: string;
       title: string;
       status: Enums.Status;
   }
}


To maintain the internal-ness of a TypeScript module, we will just simulate the enum, and then for the enum-using node, it will just import the external module version of the enum.


So let's define the task's status enum and make it an external module version of an enum instead. You might be wondering why we need to use const instead of enum. Later, the advantage of using const over enum will be apparent.


tasks-status-enum.ts
export const PENDING  = 0;
export const IN_PROGRESS = 1;
export const COMPLETED = 2;


task.ts:
module com.anicehumble
{
   export type Status = 0 | 1 | 2;
   
   export interface Task
   {
       uuid: com.anicehumble.uuid;
       ownedBy: string;
       title: string;
       status: Status;
   }
}


The internal module version of the enum is the export type Status = 0 | 1 | 2. We will not be directly using the numbers in node, as it will look like magic numbers, we just add that to constraint the values that can be assigned to Task's status. The code below uses magic number:

const t : com.anicehumble.Task = <any>{};
t.status = 2; // http://stackoverflow.com/questions/47882/what-is-a-magic-number-and-why-is-it-bad
    

For enum-using node, this is how enum will be used:

app.ts:
import * as TaskStatus from './task-status-enum';

const t : com.anicehumble.Task = <any>{};

t.status = TaskStatus.IN_PROGRESS;

console.log(TaskStatus.IN_PROGRESS); // no more undefined error

And this will not work, as the status value is constrained to 0, 1, 2 values only:

t.status = 42; // compile error: 42 is not assignable to type Status

This will not compile as type Status and number are not type-compatible:

const n: number = 42;

t.status = n; // compile error: number is not assignable to type Status

and so is this, even if the value of 2 of n is in the allowable values of Status:

const n: number = 2;

t.status = n; // compile error: number is not assignable to type Status

And now for the interesting part, we can make things more discoverable if we will make the simulated enum have a type of com.anicehumble.Status:


tasks-status-enum.ts
export const PENDING : com.anicehumble.Status    = 0;
export const IN_PROGRESS: com.anicehumble.Status = 1;
export const COMPLETED: com.anicehumble.Status   = 2;

Adding the type to the constant, that external module version of simulated enum is now related to the internal module version of the enum (i.e., export type Status = 0 | 1 | 2)

With real enum, the type cannot be added, the following is invalid:

export enum Status
{
    PENDING : com.anicehumble.Status    = 0,
    IN_PROGRESS: com.anicehumble.Status = 1,
    COMPLETED: com.anicehumble.Status   = 2
}


Update

Had I known TypeScript's const enum from the start, this post will not be written. Use const enum, it's better than what was suggested here.



Happy Coding!

Sunday, January 1, 2017

Error: request entity too large

return this.$http.post(
'/great/api/-core/file/jpg',
formData,
{
    transformRequest: angular.identity
    // , headers: { 'Content-Type': undefined } // uncomment this to remove the error: Request Entity Too Large 
 });


Happy Coding!