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 = someObj
So 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]