When and how to use interfaces in typescript. TL;DR - to prepare tymplates for objects.
Simple function, not many parameters - interface not needed:
let drawPoint = (x, y) => {
console.log("kotek")
}When many parameters would be needed, you shouldn't pass all of them (doesn't read well)
let drawPointTwo = (x, y, z, w, e, d, a) => {
console.log("kotek")
}Instead of passing multiple parameters, pass an object
let drawPointThree = (properties) => {
console.log("kotek")
}
drawPointThree({
direction: "north",
name: "jusia",
school: "VLO",
cats: ["kotek", "psotek"]
})
The problem with this solution is that we don't verify what's inside fo the object, we can pass numbers instead of string only and it's still going to be ok
let drawPointFour = (properties) => {
console.log("kotek")
}
drawPointFour({
direction: 1,
name: 2,
school: 3,
cats: 4
})In order to tell what types of parameters we expect we could use inline annotation. However, it's a bit verbose, need to repeat the notation each time a function is called.
let drawPointFive = (properties: {direction: number, name: number, school: number, cats: number}) => {
console.log("kotek")
}
drawPointFive({
direction: 1,
name: 2,
school: 3,
cats: 4
})
drawPointFive({
direction: "south", // [ts] Property 'foo' does not exist on type 'Properties'. [2339]
name: "kociasia",
school: 3,
cats: 4
})In order to keep the annotation but without the need of rewriting it every time as above, we can use iterfaces!
interface Properties {
direction: string,
name: string,
age: number,
cats: string[],
doSomething(): string;
}doSomething method - you can't create method implementation in interface, only method signature, later class will implement it. doSomething is a method that takes no input arguments and returns a string.
let drawPointSix = (properties: Properties) => {
console.log("kotek")
}Above we define a method with Properties as a type of argument.
Below we call the method by passing an object whose content matches the requirements of the interface (it doesn't explicitly implement the interfact, but typescript is ok with duck typing - see below)
drawPointSix({
direction: "north",
name: "kot",
age: 28,
cats:["kot", "psot"],
doSomething: () => {
return "kot"
}
})Now let's take a look at a class implementing interface and duck typing.
class Kotek implements Properties {
direction: string;
name: string;
age: number;
cats: string[];
doSomething(): string {
throw new Error("Method not implemented.");
}
}
let aKotek: Properties = new Kotek();Kotek implements Properties interface this is why this works.
In typescript you can create object that implements interface even (all properties) even though it's not an instance of a class that implements an interface
let someObj = {
direction: "south",
name: "jusia",
age: 30,
cats: ["a", "b"],
doSomething: () => "Test"
}The object above is not an instance of class Kotek and doesn't implement the interface.
Even though Typescript allows to treat is as instance of Kotek! As long as it matched the structure :D :D :D - DUCK TYPING
aKotek = someObjSo we can assing someObj to aKotek as someObj satisfies the contract of Properties interface that Kotek class implements.
However, as we assigned, be can't access the additional field of someObj as it's not existing on interface Properties.
aKotek.foo // [ts] Property 'foo' does not exist on type 'Properties'. [2339]