«The World’s Most Misunderstood Programming Language Has Become the World’s Most Popular Programming Language»
> '5' - 3
> '5' + 3
> '5' + - '2'
> 5 + {v: 2}
> 5 - {v: 2}
< 2 // Number
< '53' // String
< '5-2' // String
< '5[object Object]' // String
< NaN // NaN Number
> typeof "hello world"
< "string"
> typeof new String('hello world')
< "object"
Typescript
Anders Hejlsberg created:
public ngOnInit(): void {
const movie = {
name: 'Game of Thrones',
};
this.showToast(movie);
}
private showToast(item: any): void {
this.toaster.show(`Today's movie is: ${item.name}`);
}
public ngOnInit(): void {
const movie = {
title: 'Game of Thrones',
};
this.showToast(movie);
}
private showToast(item: any): void {
this.toaster.show(`Today's movie is: ${item.name}`);
}
interface Movie {
name: string;
}
public ngOnInit(): void {
const movie: Movie = {
name: 'Game of Thrones',
};
this.showToast(movie);
}
private showToast(item: Movie): void {
this.toaster.show(`Today's movie is: ${item.name}`);
}
interface Movie {
title: string;
}
public ngOnInit(): void {
const movie: Movie = {
name: 'Game of Thrones',
};
this.showToast(movie);
}
private showToast(item: Movie): void {
this.toaster.show(`Today's movie is: ${item.name}`);
}
interface Movie {
name: string;
}
public ngOnInit(): void {
const movie: Movie = {
name: 'Game of Thrones',
};
this.showToast(movie);
}
private showToast(item: Movie): void {
this.toaster.show(`Today's movie is: ${item['name']`);
}
interface Movie {
name: string;
genre: string;
}
getMovieProp(key: keyof Movie, movie: Movie): string {
return movie[key as string]?.toString();
}
private showToast(item: Movie): void {
this.toaster.show(getMoviewProp('name'));
}
// Typescript
export class SampleService {
public multiply(num: number, num2: number): number {
return num * num2;
}
}
// Javascript
"use strict";
Object.defineProperty(exports, "__esModule",
{ value: true });
class SampleService {
multiply(num, num2) {
return num * num2;
}
}
exports.SampleService = SampleService;
const arg1 = 2, arg2 = 3;
const result1 = service.multiply(arg1, arg2);
// result = 6
const arg1 = 2, arg2: any = '3';
const result1 = service.multiply(arg1, arg2);
// result = 6
const arg1 = 2, arg2: any = 'foo';
const result1 = service.multiply(arg1, arg2);
// result = NaN
const arg1 = 2, arg2: any = { name: 'foo' };
const result1 = service.multiply(arg1, arg2);
// result = NaN
const arg1 = 9, arg2: any = '9';
const result1 = service.sum(arg1, arg2);
// result = 99
// usage of ANY
const arg1: any;
function (arg: any) {...}
// usage of literal properties
const obj = getObj();
someFunc(obj['prop']);
multiplyChecked(num: number, num2: number): number {
if (typeof num !== 'number') {
throw Error(`Wrong arg 1: ${typeof num}`)
}
if (typeof num2 !== 'number') {
throw Error(`Wrong arg 2: ${typeof num2}`)
}
return num * num2;
}
@Typed()
public multiplyChecked(num: number, num2: number): number {
return num * num2;
}
export function Typed() {
return (target: Object, propertyName: string,
descriptor: TypedPropertyDescriptor<Function>) => {
const method = descriptor.value;
descriptor.value = function() {
checkTypes(target, propertyName, arguments);
return method.apply(this, arguments);
};
};
}
import 'reflect-metadata';
function checkTypes(
target: Object, propertyName: string, args: any[]): void {
const paramTypes = Reflect.getMetadata(
'design:paramtypes', target, propertyName);
paramTypes.forEach((param, index) => {
const actualType = typeof arguments[index];
const expectedType =
param instanceof Function ? typeof param() : param.name;
if (actualType !== expectedType) {
throw new Error(`Argument: ${index} of function ${propertyName}
has type: ${actualType} different from
expected type: ${expectedType}.`);
}
});
}
__decorate([
src_1.Typed(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number, Number]),
__metadata("design:returntype", Number)
], TypedTestService.prototype, "multiplyChecked", null);
@Typed()
public multiplyChecked(num: number, num2: number): number {
return num * num2;
}
±0.2 ms
overhead for type checks
npm install ts-stronger-types --save
import * as t from 'io-ts'
const User = t.type({
userId: t.number,
name: t.string
})
npm install io-ts
import { validate } from "superstruct-ts-transformer";
type User = {
name: string;
alive: boolean;
};
const obj = validate<User>(
JSON.parse('{ "name": "Me", "alive": true }'));
npm install superstruct-ts-transformer
export class Post {
@IsString()
title: string;
@IsInt()
@Min(0)
@Max(10)
rating: number;
@IsEmail()
email: string;
@IsDate()
createDate: Date;
}
validate(obj)
.then(() => {...})
.catch(err => {...})
validate(obj)
.then(() => {...})
.catch(err => {...})
npm install class-validators --save
Suggestion from friends research