> You lose flexibility when suddenly everything is locked to each other by name. Even if Account and Person both has a first and last name fields, you can't use both of them if the function is expecting a Account and only use the first and last name. Then you need to add an interface, name it something, then make Account and Person be based on that. Now the function is locked to the interface, and so on
I see this argument frequently, and it doesn't make sense to me. Take the following function below in JavaScript and Typescript:
function fullNameUntyped(obj) {
return `${obj.firstName} ${obj.lastName}`;
}
type FirstAndLastName = { firstName: string, lastName: string };
function fullNameTyped(obj: FirstAndLastName): string {
return `${obj.firstName} ${obj.lastName}`;
}
In both cases, the function's argument is bound to the interface represented by
FirstAndLastName. The difference is that TypeScript allows you to be explicit about it and can statically determine if your code conforms to this. Without static type checking, you're
implicitly bound to that interface.
Also, you seem to have a misunderstanding. TypeScript is Duck-typed. This means that interface compliance is based on structure, not name. So the following code is correct and type-safe:
class Person {
personId: number;
firstName: string;
lastName: string;
constructor(firstName: string, lastName: string) {
this.personId = 0;
this.firstName = firstName;
this.lastName = lastName;
}
}
class Account {
accountId: number;
firstName: string;
lastName: string;
constructor(firstName: string, lastName: string) {
this.accountId = 0;
this.firstName = firstName;
this.lastName = lastName;
}
}
interface FirstAndLastName {
firstName: string;
lastName: string;
}
function fullName(obj: FirstAndLastName): string {
return `${obj.firstName} ${obj.lastName}`;
}
let person = new Person("John", "Doe");
let account = new Account("Jane", "Doe");
console.log(fullName(person)); // Prints "John Doe";
console.log(fullName(account)); // Prints "Jane Doe";
Both the
Person and
Account classes satisfy the interface
FirstAndLastName in structure, but they don't have to reference it at all.
> Type checking is a very basic form of testing that doesn't solve the most common, annoying and hard-to-track down bugs, logic bugs.
First of all, challenge. Types can help with logic bugs just fine, but also my guess would be that type bugs come up more often. This includes typos, using the wrong variables, incorrect function argument order, etc. But I'd like to see any reference for that kind of claim anyway.
Second of all, no one says you can't still can't write tests even if you're using TypeScript.
Types are some work up front but like any tool once you learn to use them it isn't really a hinderance on prototyping or experimenting-- if anything they make it easier for me. They also make it easier to refactor, since static analysis tools can help with many refactoring tasks as well.