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, 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 

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
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:

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.. 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;


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

    location / {
        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([

Happy Coding!