Skip to content

Commit 1ff6b69

Browse files
committed
improvements in language notes
1 parent 477af18 commit 1ff6b69

2 files changed

Lines changed: 118 additions & 94 deletions

File tree

02-languages/02-apuntes/01-javascript/105 destructuring.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,12 @@ console.log(iso3); // "SPA"
6767

6868
// Incluso podemos aplicar "destructuring" sobre objetos que se pasan como argumento de una
6969
// función:
70-
const student = {
71-
name: "Evan",
72-
surname: "Smith",
73-
country: "USA",
70+
71+
const showFullName = ({ name, surname }) => {
72+
console.log(`${name} ${surname}`);
7473
};
75-
const getName = ({ name }) => name;
76-
console.log(getName(student)); // "Evan"
74+
75+
showFullName(student); // "Evan Smith"
7776

7877
// "DESTRUCTURING" SOBRE ARRAYS
7978

Lines changed: 113 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,139 @@
11
///-- INTERFACES **********************************************************************************
22

3-
// Una interfaz no es más que un contrato especificando las propiedades que un objeto debe tener.
4-
// Uno de los objetivos más básicos que tienen las interfaces es que nos permiten dar nombres a
5-
// las estructuras y por lo tanto podemos reusarlos.
3+
// Una interfaz no es más que un contrato especificando las propiedades de un objeto: cómo deben
4+
// llamarse dichas propiedades y de que tipo deben ser. El objetivo de los interfaces, además de
5+
// tipar objetos, es darle nombre a las estructuras y poder reutilizarlos.
66

7-
interface Geoposition {
8-
latitude: number;
9-
longitude: number;
7+
interface Coord {
8+
lat: number;
9+
lon: number;
1010
}
1111

12-
const pos: Geoposition = {
13-
latitude: 3.3112,
14-
longitude: 5.1123,
12+
const pos: Coord = {
13+
lat: 3.3112,
14+
lon: 5.1123,
1515
};
1616

1717
// En caso de no especificar todas las propiedades lanzará un error de compilación
18-
const pos1: Geoposition = {
19-
// ^^^^ [ts] Type '{ latitude: number; }' is not assignable to type 'Geoposition'.
20-
latitude: 3.3112,
18+
const pos: Coord = {
19+
// ^^^^ [ts] Property 'lon' is missing in type '{ lat: number; }'.
20+
lat: 3.3112,
2121
};
2222

2323
// También si especificamos propiedades por exceso, lanzaría un error.
24-
const pos2: Geoposition = {
25-
latitude: 3.3112,
26-
longitude: 5.1123,
27-
altitude: 325,
24+
const pos: Coord = {
25+
lat: 3.3112,
26+
lon: 5.1123,
27+
alt: 325, // [ts] Object literal may only specify known properties, and 'alt' does not exist in
28+
// type 'Coord'
2829
};
2930

30-
// Podemos ANIDAR, es decir, utilizar interfaces como tipos dentro de otras inferfaces:
31+
// *** Modificadores: optional & readonly *********************************************************
32+
33+
// TypeScript soporta propiedades opcionales mediante el operador [?]. Una propiedad opcional es
34+
// aquella que puede ser declarada (y por tanto tendrá un valor asignado) o no. Si no la declaramos,
35+
// su valor sería undefined.
36+
37+
// Además, podemos forzar a que ciertas propiedades sean de sólo lectura. Para ello usaremos el
38+
// operador "readonly" delante de la propiedad. Con esto conseguimos establecer el valor de la
39+
// propiedad a la hora de crear el objeto denegando la posibilidad (a nivel de compilación) de
40+
// reasignar dicha propiedad.
41+
42+
interface Coord {
43+
readonly lat: number;
44+
readonly lon: number;
45+
alt?: number;
46+
}
47+
48+
const pos: Coord = {
49+
lat: 3.3112,
50+
lon: 5.1123,
51+
// alt: 350, // Optional
52+
};
53+
54+
pos.lat = 3.4567; // [ts] Cannot assign to 'lat' because it is a read-only property
55+
56+
57+
// *** Anidamiento y extensión de interfaces ******************************************************
58+
59+
// Podemos anidar interfaces dentro de otros. Esta es una forma jerárquica de componer interfaces,
60+
// por ejemplo:
61+
3162
interface Address {
3263
zipCode: number;
3364
city: string;
3465
street: string;
3566
}
3667

37-
interface Citizen {
38-
name: string;
68+
interface Coord {
69+
lat: number;
70+
lon: number;
3971
address: Address;
4072
}
4173

42-
const citizen: Citizen = {
74+
const place: Coord = {
75+
lat: 3.3112,
76+
lon: 5.1123,
4377
address: {
4478
city: "Málaga",
4579
street: "Héroes de Sostoa",
4680
zipCode: 29002,
4781
},
48-
name: "Javier",
4982
};
5083

51-
// *** Propiedades Opcionales
52-
// TypeScript soporta propiedades opcionales mediante el operador [?]. Una propiedad opcional no es
53-
// más que aquella cuyo valor puede ser ser definido o no (en este segundo caso sería undefined).
84+
// También es frecuente utilizar la extensión de interfaces como método de composición. Es decir,
85+
// una interfaz puede extender de otra para combinar propiedades:
5486

55-
// Podemos definir propiedades opcionales de una interfaz
56-
interface Book {
57-
isbn: number;
58-
author?: string;
59-
}
60-
const book1: Book = { isbn: 764589621 };
61-
console.log(book1.author); // undefined
62-
const book2: Book = { isbn: 854632187, author: "Rolan" };
63-
console.log(book2.author); // Rolan
64-
65-
// *** Propiedades Read-Only
66-
// Podemos forzar a que ciertas propiedades sean de sólo lectura. Para ello usaremos el operador
67-
// "readonly" delante de la propiedad. Con esto conseguimos establecer el valor de la propiedad a
68-
// la hora de crear el objeto denegando la posibilidad (a nivel de compilación) de reasignar
69-
// dicha propiedad:
70-
interface Product {
71-
readonly id: number;
72-
stock: number;
87+
interface Address {
88+
zipCode: number;
89+
city: string;
90+
street: string;
7391
}
74-
const product: Product = { id: 998, stock: 0 };
75-
product.stock = 20;
76-
product.id = 339; // [ts] Cannot assign to 'id' because it is a constant or a 'read-only' property
7792

78-
// Extendiendo interfaces
79-
interface MyEvent {
80-
type: string;
93+
interface Coord {
94+
lat: number;
95+
lon: number;
8196
}
8297

83-
interface MyKeyboardEvent extends MyEvent {
84-
key: string;
98+
interface Place extends Coord {
99+
address: Address;
85100
}
86101

87-
const keyboardEvent: MyKeyboardEvent = {
88-
key: "shift",
89-
type: "keyboard event",
102+
const place: Place = {
103+
lat: 3.3112,
104+
lon: 5.1123,
105+
address: {
106+
city: "Málaga",
107+
street: "Héroes de Sostoa",
108+
zipCode: 29002,
109+
},
90110
};
91111

92-
// Podemos extender de varias interfaces a la vez, esto es posible ya que las interfaces sólo
93-
// especifican las propiedades que un objeto debe de tener (a pesar de usar extends no tiene
94-
// por qué estar relacionado con la herencia prototípica)
112+
// Incluso sería posible la extensión múltiple:
113+
interface Place extends Coord, Address {}
95114

96-
interface Soldier {
97-
swordType: string;
98-
}
115+
const place: Place = {
116+
lat: 3.3112,
117+
lon: 5.1123,
118+
city: "Málaga",
119+
street: "Héroes de Sostoa",
120+
zipCode: 29002,
121+
};
99122

100-
interface Ranger {
101-
ammoType: string;
102-
totalAmmo: number;
103-
}
123+
// *** Duck typing ********************************************************************************
104124

105-
interface Ninja extends Soldier, Ranger {
106-
smokeBombs: number;
107-
}
125+
// TypeScript no tan estricto a la hora de tipar como pudiera parecer a priori y no ejecuta un
126+
// chequeo semántico de los tipos sino que hace una comparación estructural.
108127

109-
const ninja: Ninja = {
110-
swordType: "katana",
111-
ammoType: "shuriken",
112-
totalAmmo: 10,
113-
smokeBombs: 3,
114-
};
128+
// Es decir, al trabajar con interfaces, TypeScript NO comprueba que un objeto o instancia es de
129+
// tipo "X" (comprobación semántica) sino que comprueba que su estructura es compatible con el
130+
// contrato que indica el tipo "X" (comprobación estructural).
131+
132+
// Como curiosidad, el nombre de duck typing viene de un antiguo dicho: "Si camina como un pato,
133+
// nada como un pato y hace cuack, entonces es que probablemente sea un pato".
134+
135+
// Vemos el siguiente ejemplo:
115136

116-
// *** Duck typing
117-
// TypeScript no tan estricto a la hora de tipar y no tiene en cuenta semánticamente los tipos,
118-
// sino que sigue una comparación estructural. Vemos el siguiente ejemplo:
119137
interface User {
120138
id: number;
121139
name: string;
@@ -147,29 +165,36 @@ printUserName(julia);
147165
// Pero tampoco hay problemas a la hora de utilizarlo con un objeto de tipo Dog
148166
printUserName(laika);
149167

150-
// Esto es, por lo que decimos, User y Dog comparten la misma estructura, si intentamos usarlo con
151-
// otra interfaz que no comparta sus mismos atributos dará un error de tipos
168+
// ¿Cómo es posible que pueda pasar como argumento 'user' un objeto de tipo Dog? Porque, aun siendo
169+
// objetos de tipos diferentes, los interfaces User y Dog comparten la misma estructura.
170+
// Y TypeScript no hace un chequeo semántico, es decir, no comprueba que el argumento user tenga que
171+
// estar forzosamente tipado con el interface User sino que comprueba que su estructura encaja con
172+
// lo especificado en dicho interface.
173+
174+
// Si intentamos usarlo con otra interfaz que no comparta sus mismos atributos dará un error
175+
// de tipos:
176+
152177
interface Cat {
153178
name: string;
154179
}
155180

156181
const garfield: Cat = { name: "Garfield" };
182+
183+
// Garfield no tiene "id: number" por lo que no es compatible con el tipo esperado para
184+
// el argumento user
157185
printUserName(garfield);
158-
// Garfield no tiene "id: number" por lo que no compatible con el tipo que necesita
159186

160-
// Como vemos si la interfaz no tiene las propiedades requeridas no podrá ser usado por la función.
161-
// Sin embargo esto no significa que la interfaz pueda tener más propiedades
187+
// Como vemos, si la interfaz no tiene, como mínimo, las propiedades requeridas no podrá ser usada
188+
// como argumento de la función.
189+
// Sin embargo, si dispone de las propiedades necesarias cómo mínimo, aunque tenga más propiedades,
190+
// si que podría validarse debido al duck typing:
162191

163-
interface Fish {
192+
interface Cat {
164193
id: number;
165194
name: string;
166-
colors: string[];
195+
color: string;
167196
}
168197

169-
const bob: Fish = { id: 319, name: "Bob", colors: ["white", "yellow"] };
170-
printUserName(bob);
171-
// bob al tener "id: number" y "name: string" es compatible, pese a tener más propiedades de
172-
// las requeridas
198+
const garfield: Cat = { id: 43, name: "Garfield", color: "orange" };
173199

174-
// Es decir, actualmente la función printUserName necesita un objeto que estructuralmente tenga
175-
// como mínimo las dos propiedades de User,
200+
printUserName(garfield); // OK!

0 commit comments

Comments
 (0)