TypeScript's type checking focuses on the shape that values have. This is called 'duck typing' or 'structural subtyping'.
In TypeScript, interfaces fill the role of naming these types and are a powerful way of defining contracts within code as well as contracts with code outside of the project.
interface IToDoItem {
text: string;
isCompleted: boolean
}
function addItem(item: IToDoItem) {
console.log(item.text);
}
let newItem = { text: 'Write posting', isCompleted: false };
addItem(newItem);
// Writing posting
This is a simple example of an Interface.
Optional Properties
Some properties exist under certain conditions or may not be there at all.
interface IToDoItem {
text: string;
priority?: number;
isCompleted: boolean;
}
function addItem(item: IToDoItem) {
console.log(`${item.priority}: ${item.text}`);
}
let newItem1 = { text: 'Write posting', isCompleted: false };
addItem(newItem1);
// undefined: Write posting
let newItem2 = { text: 'Do a homework', priority: 1, isCompleted: false };
addItem(newItem2);
// 1: Do a homework
Each optional property denoted by a ? at the end of the property name in the declaration.
Readonly Properties
You can specify read-only properties by putting readonly before the name of the property.
interface IToDoItem {
readonly owner: string;
text: string;
isCompleted: boolean;
}
function addItem(item: IToDoItem) {
console.log(`${item.text} by ${item.owner}`);
item.owner = 'kim' // Error: it is a read-only property.
}
let newItem = { owner: 'hoya', text: 'Write posting', isCompleted: false };
addItem(newItem);
// Write posting by hoya
TypeScript provide a ReadonlyArray<T> type.
let roArr: ReadonlyArray<number> = [1, 2, 3];
let nArr: Array<number>;
roArr[0] = 4; // Error: it only permits reading.
nArr = roArr; // Error: readonly type cannot be assigned to the mutable type.
nArr = roArr as Array<number>;
If you want to assign a read-only type to the mutable type, you have to use a type assertion.
Remember it, variables use const whereas properties use readonly.
Function Types
To describe a function type with an interface, we give the interface a call signature.
interface CompareFunc {
(param1: number, param2: number): boolean;
}
let myFunc: CompareFunc = function (param1: number, param2: number) {
return param1 > param2;
};
console.log(myFunc(2, 4));
// false
The names of the parameters can be different.
interface CompareFunc {
(param1: number, param2: number): boolean;
}
let myFunc: CompareFunc = (p1: number, p2: number): boolean => {
return p1 > p2;
};
console.log(myFunc(4, 2));
// true
If you skip the specifying the argument types, TypeScript will infer it.
interface CompareFunc {
(param1: number, param2: number): boolean;
}
let myFunc: CompareFunc = (p1, p2) => {
return p1 > p2;
};
console.log(myFunc(1, 3));
// false
Indexable Types
Indexable types have an index signature that describes the types we can use to index into the object, along with the corresponding return types when indexing.
interface StringArray {
[index: number]: string;
}
let arr: StringArray = ['tomato', 'potato'];
console.log(arr[1]);
// potato
There are two types of supported index signatures: string and number.
interface Fruit {
name: string;
}
interface FruitArray {
[x: number]: Fruit;
}
let arr: FruitArray = ['apple', 'banana', 'cherry']; // Error: type string is not assignable to type Fruit
The type returned from a numeric indexer must be a subtype of the type returned from the string indexer.
This is because when indexing with a number, JavaScript will actually convert that to a string before indexing into an object.
Class Types
interface ShoppingCart {
item: string;
count: number;
addItem(name: string): void;
removeItem(name: string): void;
}
class Shop implements ShoppingCart {
item: string;
count: number;
addItem(name: string) {
++this.count;
}
// Error: Property removeItem is missing.
constructor() {
this.item = "";
this.count = 0;
}
}
TypeScript is also possible, as in languages such as C# and Java, which explicitly enforcing that a class meets a particular contract.
Extending Interfaces
interface Fruit {
name: string;
}
interface Mart extends Fruit {
count: number;
}
let mart = { name: 'Apple', count: 5 } as Mart;
console.log(mart);
// {name: 'Apple', count: 5}
Interfaces can extend each other, and an interface can extend multiple interfaces.
Hybrid Types
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
const counter = function (start: number) {
console.log(`This is a counter function.`)
} as Counter;
counter.interval = 30;
counter.reset = function () {
console.log('This is a reset function.')
};
return counter;
}
let c = getCounter();
c(10);
// This is a counter function.
c.reset();
// This is a reset function.
c.interval = 5;
Interfaces can describe the rich types present in JavaScript.
Interfaces Extending Classes
class Parent {
private parentVar: any;
}
interface Child extends Parent {
childFunc(): void;
}
class GrandChild implements Child {
// Error: it is missing the 'parentVar' and 'childFunc'.
private grandChildVar: any;
grandChildFunc() {}
}
When an interface type extends a class type it inherits the members of the class but not their implementations.
It is as if the interface had declared all of the members of the class without providing an implementation.
'Web > JavaScript' 카테고리의 다른 글
[TypeScript] Decorators (0) | 2020.10.24 |
---|---|
[TypeScript] Iterators and Generators (0) | 2020.10.23 |
[TypeScript] Destructuring and Spread (0) | 2020.10.16 |
[TypeScript] Variable Declaration (var, let, const) (0) | 2020.10.15 |
[TypeScript] Dev. Environment Configuration with VS Code (0) | 2020.10.12 |
댓글