ΠΠΎΡΠ΅ΠΌΡ ΡΡΠΎΠΈΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Tagged Unions ΠΏΡΠΈ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠ΅ Π½Π° TypeScript
- Π²ΡΠΎΡΠ½ΠΈΠΊ, 5 Π°Π²Π³ΡΡΡΠ° 2025β―Π³. Π² 00:00:02
π ΠΡΠΈΠ²Π΅Ρ! ΠΠ΅Π½Ρ Π·ΠΎΠ²ΡΡ ΠΠ»Π΅ΠΊΡΠ°Π½Π΄Ρ, Ρ ΡΠ°Π±ΠΎΡΠ°Ρ ΡΡΠΎΠ½ΡΠ΅Π½Π΄-ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠΌ Π² ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ Β«ΠΠ΅Π³Π°Π€ΠΎΠ½Β». Π‘Π΅Π³ΠΎΠ΄Π½Ρ Ρ Ρ ΠΎΡΡ ΠΏΠΎΠ³ΠΎΠ²ΠΎΡΠΈΡΡ Π½Π° ΡΠ΅ΠΌΡ Tagged Unions (ΡΠ°Π·ΠΌΠ΅ΡΠ΅Π½Π½ΡΡ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ) ΠΈ ΠΎΠ±ΡΡΡΠ½ΠΈΡΡ, ΠΏΠΎΡΠ΅ΠΌΡ ΠΎΠ½ΠΈ β Π²Π°Ρ ΡΠ΅ΠΊΡΠ΅ΡΠ½ΡΠΉ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½Ρ Π΄Π»Ρ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΡ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΠ³ΠΎ TypeScript-ΠΊΠΎΠ΄Π°.
Π Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ½ΠΎ ΡΠ°Π·Π²ΠΈΠ²Π°ΡΡΠ΅ΠΌΡΡ ΠΌΠΈΡΠ΅ Π²Π΅Π±-ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΠ³ΠΎ, ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΡΠ΅ΠΌΠΎΠ³ΠΎ ΠΈ Π»Π΅Π³ΠΊΠΎ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΠΌΠΎΠ³ΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΠΎΠ³ΠΎ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΡ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΊΠ»ΡΡΠ΅Π²ΠΎΠΉ Π·Π°Π΄Π°ΡΠ΅ΠΉ. TypeScript, Π±ΡΠ΄ΡΡΠΈ ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΡΠΈΠΏΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠΌ ΡΡΠΏΠ΅ΡΡΠ΅ΡΠΎΠΌ JavaScript, Π±ΡΠ» ΡΠ°Π·ΡΠ°Π±ΠΎΡΠ°Π½ ΠΈΠΌΠ΅Π½Π½ΠΎ Π΄Π»Ρ ΡΠ΅ΡΠ΅Π½ΠΈΡ ΡΡΠΈΡ Π²ΡΠ·ΠΎΠ²ΠΎΠ², ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎ Π² ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ΅ Π±ΠΎΠ»ΡΡΠΈΡ ΠΊΠΎΠ΄ΠΎΠ²ΡΡ Π±Π°Π· ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ ΡΠ°Π±ΠΎΡΡ.
ΠΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΡΠΈΠΏΠΎΠ² ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°ΠΌ Π²ΡΡΠ²Π»ΡΡΡ ΠΎΡΠΈΠ±ΠΊΠΈ Π½Π° ΡΡΠ°ΠΏΠ΅ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ, Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΡΠΎΠΊΡΠ°ΡΠ°Ρ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ Π±Π°Π³ΠΎΠ², ΠΏΠΎΠΏΠ°Π΄Π°ΡΡΠΈΡ Π² ΠΏΡΠΎΠ΄Π°ΠΊΡΠ½, ΠΈ ΡΠ»ΡΡΡΠ°Ρ ΠΏΡΠ΅Π΄ΡΠΊΠ°Π·ΡΠ΅ΠΌΠΎΡΡΡ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ. Π‘ΡΡΠΎΠ³Π°Ρ ΡΠΈΠΏΠΈΠ·Π°ΡΠΈΡ Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΠ²ΡΡΠ°Π΅Ρ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΡΡΡ ΠΊΠΎΠ΄Π°, Π½ΠΎ ΠΈ ΡΠ»ΡΡΡΠ°Π΅Ρ Π΅Π³ΠΎ ΡΠΈΡΠ°Π΅ΠΌΠΎΡΡΡ, ΠΎΠ±Π»Π΅Π³ΡΠ°Π΅Ρ ΠΏΡΠΎΡΠ΅ΡΡΡ ΡΠ΅ΡΠ°ΠΊΡΠΎΡΠΈΠ½Π³Π° ΠΈ ΡΠΏΠΎΡΠΎΠ±ΡΡΠ²ΡΠ΅Ρ Π±ΠΎΠ»Π΅Π΅ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΠΉ ΠΊΠΎΠ»Π»Π°Π±ΠΎΡΠ°ΡΠΈΠΈ ΠΌΠ΅ΠΆΠ΄Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°ΠΌΠΈ.
ΠΠ΄Π½Π°ΠΊΠΎ, Π±Π΅Π· ΡΠ²Π½ΠΎΠ³ΠΎ ΠΈ ΡΡΡΡΠΊΡΡΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΡΠΈΠΏΠ°ΠΌΠΈ Π΄Π°ΠΆΠ΅ Π² TypeScript ΠΌΠΎΠ³ΡΡ Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ. ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠΈΡΠΎΠΊΠΈΡ
ΡΠΈΠΏΠΎΠ², Π½Π΅Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½ΠΈΡΠΎΠ²Π°Π½Π½ΡΡ
ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, string | number
ΠΈΠ»ΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΡ Ρ ΠΎΠΏΡΠΈΠΎΠ½Π°Π»ΡΠ½ΡΠΌΠΈ ΡΠ²ΠΎΠΉΡΡΠ²Π°ΠΌΠΈ, ΡΠ°ΠΊΠΈΠΌΠΈ ΠΊΠ°ΠΊ { propA?: string } | { propB?: number }
), ΠΌΠΎΠΆΠ΅Ρ ΠΏΡΠΈΠ²Π΅ΡΡΠΈ ΠΊ ΡΠΈΡΡΠ°ΡΠΈΡΠΌ, ΠΊΠΎΠ³Π΄Π° ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡ Π½Π΅ ΡΠΏΠΎΡΠΎΠ±Π΅Π½ ΡΠΎΡΠ½ΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΡ ΡΠ΅ΠΊΡΡΠΈΠΉ ΡΠΈΠΏ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ. ΠΡΠΎ Π·Π°ΡΡΡΠ΄Π½ΡΠ΅Ρ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠΉ Π΄ΠΎΡΡΡΠΏ ΠΊ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ½ΡΠΌ ΡΠ²ΠΎΠΉΡΡΠ²Π°ΠΌ, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π΄ΠΎΡΡΡΠΏΠ½Ρ ΡΠΎΠ»ΡΠΊΠΎ ΡΠ΅, ΠΊΠΎΡΠΎΡΡΠ΅ Π³Π°ΡΠ°Π½ΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎ ΠΏΡΠΈΡΡΡΡΡΠ²ΡΡΡ Π²ΠΎ Π²ΡΠ΅Ρ
ΡΠΎΡΡΠ°Π²Π»ΡΡΡΠΈΡ
ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ. Π ΡΠ°ΠΊΠΈΡ
ΡΡΠ΅Π½Π°ΡΠΈΡΡ
ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°ΠΌ ΠΏΡΠΈΡ
ΠΎΠ΄ΠΈΡΡΡ ΠΏΠΎΠ»Π°Π³Π°ΡΡΡΡ Π½Π° ΡΡΡΠ½ΡΠ΅ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ Π½Π°Π»ΠΈΡΠΈΡ ΡΠ²ΠΎΠΉΡΡΠ² (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, "property" in object
) ΠΈΠ»ΠΈ ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡ typeof
.
ΠΡΠΈ ΠΏΠΎΠ΄Ρ ΠΎΠ΄Ρ ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ Π½Π΅Π½Π°Π΄Π΅ΠΆΠ½ΡΠΌΠΈ, ΠΎΠ½ΠΈ Π½Π΅ Π³Π°ΡΠ°Π½ΡΠΈΡΡΡΡ ΠΈΡΡΠ΅ΡΠΏΡΠ²Π°ΡΡΠ΅ΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π²ΡΠ΅Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΡ Π²Π°ΡΠΈΠ°Π½ΡΠΎΠ² ΠΈ, ΡΡΠΎ ΠΊΡΠΈΡΠΈΡΠ½ΠΎ, ΠΌΠΎΠ³ΡΡ Π»Π΅Π³ΠΊΠΎ ΡΠ»ΠΎΠΌΠ°ΡΡΡΡ ΠΏΡΠΈ ΡΠ΅ΡΠ°ΠΊΡΠΎΡΠΈΠ½Π³Π΅, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ Π² ΠΎΠ΄Π½ΠΎΠΉ ΡΠ°ΡΡΠΈ ΠΊΠΎΠ΄Π° Π½Π΅ Π²ΡΠ΅Π³Π΄Π° Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΈΠ²Π°ΡΡ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΡ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ Π² Π΄ΡΡΠ³ΠΈΡ .
Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ ΠΏΡΠΈΠΌΠ΅Ρ, Π³Π΄Π΅ ΠΎΠ±ΡΡΠ½ΡΠ΅ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Π½Π΅ Π΄Π°ΡΡ Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎΠΉ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ Π΄Π»Ρ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΠ³ΠΎ Π΄ΠΎΡΡΡΠΏΠ° ΠΊ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΠΌ ΡΠ²ΠΎΠΉΡΡΠ²Π°ΠΌ:
interface Car {
Β move(): void;
Β startEngine(): void;
}
interface Bicycle {
Β move(): void;
Β gearCount: number;
}
declare function getVehicle(): Car | Bicycle;
let vehicle = getVehicle();
vehicle.move(); // OK, move() - ΠΎΠ±ΡΠ΅Π΅ ΡΠ²ΠΎΠΉΡΡΠ²ΠΎ Π΄Π»Ρ ΠΎΠ±ΠΎΠΈΡ
ΡΠΈΠΏΠΎΠ²
vehicle.startEngine(); // ΠΡΠΈΠ±ΠΊΠ° ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ:
// Π‘Π²ΠΎΠΉΡΡΠ²ΠΎ 'startEngine' ΠΎΡΡΡΡΡΡΠ²ΡΠ΅Ρ Π² ΡΠΈΠΏΠ΅ 'Car | Bicycle'. Β
// TypeScript Π½Π΅ Π·Π½Π°Π΅Ρ, ΡΠ²Π»ΡΠ΅ΡΡΡ Π»ΠΈ 'vehicle' ΠΌΠ°ΡΠΈΠ½ΠΎΠΉ ΠΈΠ»ΠΈ Π²Π΅Π»ΠΎΡΠΈΠΏΠ΅Π΄ΠΎΠΌ Π±Π΅Π· Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎΠΉ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ. Β
if ("startEngine" in vehicle) { vehicle.startEngine(); }
// ΠΡΠΎΡ ΠΊΠΎΠ΄ Π±ΡΠ΄Π΅Ρ ΡΠ°Π±ΠΎΡΠ°ΡΡ, Π½ΠΎ ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠ΄Π΅Π»Π°ΡΡ ΠΏΡΠΎΠ²Π΅ΡΠΊΡ Π² ΡΠ°Π½ΡΠ°ΠΉΠΌΠ΅.
// Π ΡΠΎΠΌΡ ΠΆΠ΅ ΡΡΠΎ Π½Π΅ Π³Π°ΡΠ°Π½ΡΠΈΡΡΠ΅Ρ ΠΏΠΎΠ»Π½ΠΎΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π²ΡΠ΅Ρ
ΡΠ»ΡΡΠ°Π΅Π².
Π ΡΠ°ΠΊΠΈΡ ΡΠ»ΡΡΠ°ΡΡ TypeScript Π½Π΅ Π΄Π°ΡΡ Π²Π°ΠΌ ΡΠ΄Π΅Π»Π°ΡΡ ΡΡΠΎ-ΡΠΎ ΡΠ²Π½ΠΎ Π½Π΅Π΄ΠΎΠΏΡΡΡΠΈΠΌΠΎΠ΅, Π½ΠΎ ΠΈ ΡΠ΄ΠΎΠ±Π½ΠΎΠ³ΠΎ ΠΈ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΠ³ΠΎ ΡΠΏΠΎΡΠΎΠ±Π° ΡΠ°Π±ΠΎΡΠ°ΡΡ Ρ ΠΊΠ°ΠΆΠ΄ΡΠΌ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠΌ ΡΠΈΠΏΠΎΠΌ Π²Π½ΡΡΡΠΈ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Ρ Π½Π΅Π³ΠΎ Π½Π΅Ρ.
ΠΠΌΠ΅Π½Π½ΠΎ Π·Π΄Π΅ΡΡ Π½Π° ΡΡΠ΅Π½Ρ Π²ΡΡ
ΠΎΠ΄ΡΡ Tagged Unions (ΠΈΠ»ΠΈ Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ). ΠΠ½ΠΈ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΡΡ ΡΠΎΠ±ΠΎΠΉ ΠΌΠΎΡΠ½ΡΠΉ ΠΏΠ°ΡΡΠ΅ΡΠ½, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠ΅ΡΠ°Π΅Ρ ΡΡΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ ΡΠΈΠΏΡ, ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΡΡΠΈΠ΅ ΠΎΠ΄Π½Ρ ΠΈΠ· Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ
Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΡ
ΡΠΎΡΠΌ, ΠΊΠ°ΠΆΠ΄Π°Ρ Ρ ΠΎΡΠ»ΠΈΡΠΈΡΠ΅Π»ΡΠ½ΡΠΌ ΡΠ²ΠΎΠΉΡΡΠ²ΠΎΠΌ β "ΡΠ΅Π³ΠΎΠΌ" ΠΈΠ»ΠΈ "Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΎΡΠΎΠΌ". ΠΡΠΎ Π½Π΅ ΠΏΡΠΎΡΡΠΎ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π΅ΡΠ΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΡΠΈΠΏΠ° ΠΈΠ»ΠΈ ΡΠ»ΡΡΡΠ΅Π½ΠΈΠ΅ ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠΈΡ
ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ, ΡΡΠΎ ΡΡΠ½Π΄Π°ΠΌΠ΅Π½ΡΠ°Π»ΡΠ½ΡΠΉ ΡΠ΄Π²ΠΈΠ³ Π² ΠΏΠΎΠ΄Ρ
ΠΎΠ΄Π΅ ΠΊ ΠΌΠΎΠ΄Π΅Π»ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π΄Π°Π½Π½ΡΡ
. ΠΡΠΎΡΡΡΠ΅ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΡΠΎΠ»ΡΠΊΠΎ ΡΠΊΠ°Π·ΡΠ²Π°ΡΡ, ΡΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΡΠΈΠΏΠΎΠΌ ΠΒ ΠΈΠ»ΠΈΒ Π.Β Tagged UnionΒ Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅Ρ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΡ ΠΌΠ΅ΡΠΊΡ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ,Β kind: 'A'
ΠΈΠ»ΠΈ kind: 'B'
), ΠΊΠΎΡΠΎΡΠ°Ρ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ TypeScript ΡΠΎΡΠ½ΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΡ, Ρ ΠΊΠ°ΠΊΠΈΠΌ ΠΈΠΌΠ΅Π½Π½ΠΎ ΡΠΈΠΏΠΎΠΌ ΠΎΠ½ ΡΠ΅ΠΉΡΠ°Ρ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ.
Π’Π°ΠΊΠΎΠΉ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ ΠΊΡΠΈΡΠΈΡΠ΅ΡΠΊΠΈ Π²Π°ΠΆΠ΅Π½ Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΡΠ»ΠΎΠΆΠ½ΡΡ ΡΠΈΡΡΠ΅ΠΌ, Π³Π΄Π΅ Π΄Π°Π½Π½ΡΠ΅ ΠΌΠΎΠ³ΡΡ ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎ ΡΠΎΡΠΌ Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ°, ΠΈ Π³Π΄Π΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ Π²ΡΡΠΎΠΊΠΈΠΉ ΡΡΠΎΠ²Π΅Π½Ρ ΠΏΡΠ΅Π΄ΡΠΊΠ°Π·ΡΠ΅ΠΌΠΎΡΡΠΈ ΠΈ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΡΡΠΈ. ΠΡΠΎ Π·Π°ΡΡΠ°Π²Π»ΡΠ΅Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ² ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°ΡΡ Π΄Π°Π½Π½ΡΠ΅ ΠΊΠ°ΠΊ Π½Π°Π±ΠΎΡ ΡΠ΅ΡΠΊΠΈΡ , Π²Π·Π°ΠΈΠΌΠΎΠΈΡΠΊΠ»ΡΡΠ°ΡΡΠΈΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ. Π’Π°ΠΊΠΎΠΉ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ ΡΠ»ΡΡΡΠ°Π΅Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΡΠΈΠΏΠ°ΠΌΠΈ, Π½ΠΎ ΠΈ Π²Π΅Π΄Π΅Ρ ΠΊ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ Π±ΠΎΠ»Π΅Π΅ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°.
Tagged UnionΒ (ΡΠ°ΠΊΠΆΠ΅ ΠΈΠ·Π²Π΅ΡΡΠ½ΡΠΉ ΠΊΠ°ΠΊΒ Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°Π½ΡΠ½ΠΎΠ΅ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅, sum type, variant record,Β choice typeΒ ΠΈΠ»ΠΈΒ disjoint union) β ΡΡΠΎ ΡΠΈΠΏ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ, Π³Π΄Π΅ ΠΊΠ°ΠΆΠ΄ΡΠΉ Π²Π°ΡΠΈΠ°Π½Ρ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΎΠ±ΡΠ΅Π΅ ΡΠ²ΠΎΠΉΡΡΠ²ΠΎ-Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΎΡ Π»ΠΈΡΠ΅ΡΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠΈΠΏΠ°. ΠΡΠΎ ΡΠ²ΠΎΠΉΡΡΠ²ΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ TypeScript ΡΠΎΡΠ½ΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΡΡ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠΉ ΡΠΈΠΏ ΠΏΡΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ°Ρ ,Β Π³Π°ΡΠ°Π½ΡΠΈΡΡΡ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠΉ Π΄ΠΎΡΡΡΠΏ ΠΊ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΠΌ ΡΠ²ΠΎΠΉΡΡΠ²Π°ΠΌΒ ΠΈ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ Π²ΡΠ΅Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΡ ΡΠ»ΡΡΠ°Π΅Π².
Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΏΡΠΈΠΌΠ΅Ρ Tagged Union Π΄Π»Ρ Π³Π΅ΠΎΠΌΠ΅ΡΡΠΈΡΠ΅ΡΠΊΠΈΡ ΡΠΈΠ³ΡΡ:
interface Circle {
kind: 'circle'; // ΠΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΎΡ: ΡΠ²ΠΎΠΉΡΡΠ²ΠΎ 'kind' Ρ Π»ΠΈΡΠ΅ΡΠ°Π»ΡΠ½ΡΠΌ ΡΠΈΠΏΠΎΠΌ 'circle'
Β Β radius: number;
}
interface Rectangle {
Β Β kind: 'rectangle'; // ΠΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΎΡ: ΡΠ²ΠΎΠΉΡΡΠ²ΠΎ 'kind' Ρ Π»ΠΈΡΠ΅ΡΠ°Π»ΡΠ½ΡΠΌ ΡΠΈΠΏΠΎΠΌ 'rectangle'
Β Β width: number;
Β Β height: number;
}
type Shape = Circle | Rectangle; // ΠΠ±ΡΠ΅Π΄ΠΈΠ½ΡΡΡΠΈΠΉ ΡΠΈΠΏ, ΡΠΎΡΡΠΎΡΡΠΈΠΉ ΠΈΠ· Circle ΠΈ Rectangle
Π ΡΡΠΎΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ kind
ΡΠ²Π»ΡΠ΅ΡΡΡ ΡΠ²ΠΎΠΉΡΡΠ²ΠΎΠΌ-Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΎΡΠΎΠΌ. ΠΠ³ΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ('circle' ΠΈΠ»ΠΈ 'rectangle') ΠΎΠ΄Π½ΠΎΠ·Π½Π°ΡΠ½ΠΎ ΡΠΊΠ°Π·ΡΠ²Π°Π΅Ρ Π½Π° ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΡ ΡΠΎΡΠΌΡ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡ TypeScript ΡΠ°Π·Π»ΠΈΡΠ°ΡΡ ΡΠ»Π΅Π½Ρ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ.
ΠΠ΅Ρ
Π°Π½ΠΈΠ·ΠΌ ΡΠ°Π±ΠΎΡΡ Tagged Unions ΠΎΡΠ½ΠΎΠ²Π°Π½ Π½Π°Β Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠΌ ΡΡΠΆΠ΅Π½ΠΈΠΈ ΡΠΈΠΏΠΎΠ² ΡΠ΅ΡΠ΅Π· ΠΊΠΎΠ½ΡΡΠΎΠ»ΡΠ½ΡΠ΅ ΡΠΎΡΠΊΠΈ (type guards). Π Π±Π»ΠΎΠΊΠ°Ρ
ΡΡΠ»ΠΎΠ²Π½ΠΎΠΉ Π»ΠΎΠ³ΠΈΠΊΠΈ (switch
,Β if/else
) TypeScriptΒ Π°Π½Π°Π»ΠΈΠ·ΠΈΡΡΠ΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΎΡΠ°Β ΠΈ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ ΡΠΎΡΠ½ΡΠΉ ΡΠΈΠΏ ΠΎΠ±ΡΠ΅ΠΊΡΠ°. ΠΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡΡΒ ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ Π²Π΅ΡΠΈΡΠΈΡΠΈΡΠΎΠ²Π°ΡΡ Π΄ΠΎΡΡΡΠΏΒ ΠΊ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΠΌ ΡΠ²ΠΎΠΉΡΡΠ²Π°ΠΌ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π²Π°ΡΠΈΠ°Π½ΡΠ°, ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ ΠΈΡΠΊΠ»ΡΡΠ°Ρ ΠΎΡΠΈΠ±ΠΊΠΈ ΠΎΠ±ΡΠ°ΡΠ΅Π½ΠΈΡ ΠΊ Π½Π΅ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠΈΠΌ ΠΏΠΎΠ»ΡΠΌ.
Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ ΡΡΠ½ΠΊΡΠΈΡ, ΠΊΠΎΡΠΎΡΠ°Ρ Π²ΡΡΠΈΡΠ»ΡΠ΅Ρ ΠΏΠ»ΠΎΡΠ°Π΄Ρ ΡΠΈΠ³ΡΡΡ:
function getArea(shape: Shape): number {
Β Β switch (shape.kind) {
Β Β Β Β case 'circle':
Β Β Β Β Β Β // ΠΠ΄Π΅ΡΡ TypeScript ΡΠΎΡΠ½ΠΎ Π·Π½Π°Π΅Ρ, ΡΡΠΎ 'shape' ΡΠ²Π»ΡΠ΅ΡΡΡ ΡΠΈΠΏΠΎΠΌ Circle,
Β Β Β Β Β Β // ΠΈ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΏΡΠ΅Π΄Π»Π°Π³Π°Π΅Ρ Π΄ΠΎΡΡΡΠΏ ΠΊ ΡΠ²ΠΎΠΉΡΡΠ²Ρ 'radius'.
Β Β Β Β Β Β return Math.PI * shape.radius ** 2;
Β Β Β Β case 'rectangle':
Β Β Β Β Β Β // ΠΠ½Π°Π»ΠΎΠ³ΠΈΡΠ½ΠΎ, Π·Π΄Π΅ΡΡ 'shape' ΡΡΠΆΠ°Π΅ΡΡΡ Π΄ΠΎ ΡΠΈΠΏΠ° Rectangle,
Β Β Β Β Β Β // ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΡ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠΉ Π΄ΠΎΡΡΡΠΏ ΠΊ 'width' ΠΈ 'height'.
Β Β Β Β Β Β return shape.width * shape.height;
Β Β }
}
ΠΡΠΎΡ ΠΌΠ΅Ρ
Π°Π½ΠΈΠ·ΠΌ ΡΡΡΡΠ°Π½ΡΠ΅Ρ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎΡΡΡ Π² ΡΡΡΠ½ΡΡ
ΠΏΡΠΎΠ²Π΅ΡΠΊΠ°Ρ
typeof
ΠΈΠ»ΠΈ in
ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡΠ°Ρ
, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ ΠΌΠ΅Π½Π΅Π΅ Π½Π°Π΄Π΅ΠΆΠ½ΡΠΌΠΈ ΠΈ Π±ΠΎΠ»Π΅Π΅ ΠΌΠ½ΠΎΠ³ΠΎΡΠ»ΠΎΠ²Π½ΡΠΌΠΈ.
ΠΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΎΡ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ΅Ρ Π½Π΅ΠΎΠ΄Π½ΠΎΠ·Π½Π°ΡΠ½ΠΎΠ΅ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ Π² ΡΡΡΠΊΠΎ ΡΠ°Π·Π»ΠΈΡΠΈΠΌΡΠ΅ Π²Π°ΡΠΈΠ°Π½ΡΡ. ΠΠ΅Π· Π½Π΅Π³ΠΎ TypeScript Π·Π½Π°Π΅Ρ ΡΠΎΠ»ΡΠΊΠΎ, ΡΡΠΎ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ ΠΎΡΠ½ΠΎΡΠΈΡΡΡ ΠΊΒ A | B
, Π²ΡΠ½ΡΠΆΠ΄Π°Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ° ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π½Π΅Π½Π°Π΄ΡΠΆΠ½ΡΠ΅ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ Π΄Π»Ρ Π΄ΠΎΡΡΡΠΏΠ° ΠΊ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΠΌ ΡΠ²ΠΎΠΉΡΡΠ²Π°ΠΌ. Tagged Unions ΡΠ΅ΡΠ°ΡΡ ΡΡΠΎ ΡΠ΅ΡΠ΅Π· ΠΎΠ±ΡΠ΅Π΅ ΡΠ²ΠΎΠΉΡΡΠ²ΠΎ Ρ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΠΌ Π»ΠΈΡΠ΅ΡΠ°Π»ΠΎΠΌ Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π²Π°ΡΠΈΠ°Π½ΡΠ°. ΠΡΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ΅Β if (obj.kind === 'circle')
Β ΠΈΠ»ΠΈΒ case 'circle'
Β TypeScriptΒ ΡΠΎΡΠ½ΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΡΒ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠΉ ΡΠΈΠΏ Π²Π½ΡΡΡΠΈ Π±Π»ΠΎΠΊΠ°, Π° Π½Π΅ ΠΏΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ Π΅Π³ΠΎ. ΠΡΠΎ ΡΠΎΠ·Π΄Π°ΡΡ ΡΠ²Π½ΡΠΉ ΠΊΠΎΠ½ΡΡΠ°ΠΊΡ Ρ ΡΠΈΡΡΠ΅ΠΌΠΎΠΉ ΡΠΈΠΏΠΎΠ², ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°Ρ:
ΠΈΡΡΠ΅ΡΠΏΡΠ²Π°ΡΡΡΡ ΠΏΡΠΎΠ²Π΅ΡΠΊΡ Π²ΡΠ΅Ρ Π²Π°ΡΠΈΠ°Π½ΡΠΎΠ²
Π°Π²ΡΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π² IDE
ΠΏΡΠ΅Π΄ΡΠΊΠ°Π·ΡΠ΅ΠΌΠΎΡΡΡ ΠΊΠΎΠ΄Π° Π΄Π»Ρ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡΠ° ΠΈ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°.
Tagged Unions Π²ΡΡΠ²Π»ΡΡΡ ΡΠ»ΠΎΠΆΠ½ΡΠ΅ Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ Π½Π° ΡΡΠ°ΠΏΠ΅ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ, Π° Π½Π΅ Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ. ΠΡΠΎ ΡΠ΅Π°Π»ΠΈΠ·ΡΠ΅Ρ ΠΏΡΠΈΠ½ΡΠΈΠΏ "Shift-Left": ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ, ΠΊΠΎΡΠΎΡΡΠ΅ Π²(?) TypeScript ΠΏΡΠΎΡΠ²ΠΈΠ»ΠΈΡΡ Π±Ρ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΈ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠΈ ΠΈΠ»ΠΈ Π² ΠΏΡΠΎΠ΄Π°ΠΊΡΠ΅Π½Π΅, ΠΎΠ±Π½Π°ΡΡΠΆΠΈΠ²Π°ΡΡΡΡ ΡΡΠ°Π·Ρ ΠΏΡΠΈ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΠΈ ΠΊΠΎΠ΄Π°. ΠΡΠΎ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°Π΅Ρ:
Π Π°Π½Π½Π΅Π΅ ΠΎΠ±Π½Π°ΡΡΠΆΠ΅Π½ΠΈΠ΅ Π±Π°Π³ΠΎΠ²Β - ΠΎΡΠΈΠ±ΠΊΠΈ ΡΠΈΠΊΡΠΈΡΡΡΡΡΡ Π΄ΠΎ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ
ΠΠ°ΡΠ°Π½ΡΠΈΡ ΠΏΠΎΠ»Π½ΠΎΡΡΒ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ - ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ Π²ΡΠ΅Ρ Π²Π°ΡΠΈΠ°Π½ΡΠΎΠ² Π΄Π°Π½Π½ΡΡ
Π‘Π½ΠΈΠΆΠ΅Π½ΠΈΠ΅ ΡΡΠΎΠΈΠΌΠΎΡΡΠΈΒ - ΠΈΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° ΡΡΠ°ΠΏΠ΅ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ Π² 10-100 ΡΠ°Π· Π΄Π΅ΡΠ΅Π²Π»Π΅
Π’Π°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ ΠΏΠΎΠ²ΡΡΠ°Π΅ΡΡΡ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΡΡΡ ΠΊΠΎΠ΄Π° ΠΈ ΡΠ½ΠΈΠΆΠ°ΡΡΡΡ ΡΠΈΡΠΊΠΈ Π² ΡΠ»ΠΎΠΆΠ½ΡΡ ΠΏΡΠΎΠ΅ΠΊΡΠ°Ρ .
TypeScript ΠΌΠΎΠΆΠ΅Ρ ΠΏΡΠ΅Π΄ΡΠΏΡΠ΅Π΄ΠΈΡΡ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°, Π΅ΡΠ»ΠΈ ΠΎΠ½ Π·Π°Π±ΡΠ΄Π΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°ΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΠΉ ΡΠ»ΡΡΠ°ΠΉ Π² switch ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡΠ΅, Π³Π°ΡΠ°Π½ΡΠΈΡΡΡ, ΡΡΠΎ ΠΊΠΎΠ΄ ΡΡΠΈΡΡΠ²Π°Π΅Ρ Π²ΡΠ΅ ΡΡΠ΅Π½Π°ΡΠΈΠΈ. ΠΠΎΡ ΠΊΠ°ΠΊ ΡΡΠΎ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ Π½Π° ΠΏΡΠ°ΠΊΡΠΈΠΊΠ΅:
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number }
| { kind: "rectangle"; width: number; height: number };
function getArea(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.side ** 2;
case "rectangle":
return shape.width * shape.height;
default:
// Exhaustiveness Ρhecking
// ΠΡΠ»ΠΈ TypeScript ΠΎΠ±Π½Π°ΡΡΠΆΠΈΡ Π½Π΅ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°Π½Π½ΡΠΉ Π²Π°ΡΠΈΠ°Π½Ρ,
// shape Π·Π΄Π΅ΡΡ Π±ΡΠ΄Π΅Ρ ΠΈΠΌΠ΅ΡΡ ΡΠΈΠΏ, ΠΎΡΠ»ΠΈΡΠ½ΡΠΉ ΠΎΡ never
const _exhaustiveCheck: never = shape;
throw new Error(`Unhandled shape: ${_exhaustiveCheck}`);
}
}
ΠΡΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠΈ Π½ΠΎΠ²ΠΎΠ³ΠΎ ΡΠΈΠΏΠ° Π² ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ Typescript Π²ΡΠ΄Π°ΡΡ ΠΎΡΠΈΠ±ΠΊΡ:
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number }
| { kind: "rectangle"; width: number; height: number }
| { kind: "triangle"; base: number; height: number }; // ΠΠΎΠ²ΡΠΉ ΡΠΈΠΏ!
ERROR: Type 'triangle' is not assignable to type 'never'.
ΠΡΠΈΠ±ΠΊΠ° ΡΠΊΠ°Π·ΡΠ²Π°Π΅Ρ, ΡΡΠΎ Π²Β switch
Β ΠΎΡΡΡΡΡΡΠ²ΡΠ΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ°Β triangle
. ΠΠΎΡΠ»Π΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π½ΠΎΠ²ΠΎΠ³ΠΎ ΡΠΈΠΏΠ° Π² switchΒ shape
Β Π²Β default
Β ΡΠ½ΠΎΠ²Π° ΡΡΠ°Π½Π΅Ρ ΡΠΈΠΏΠΎΠΌΒ never
ΠΈ ΠΎΡΠΈΠ±ΠΊΠ° ΠΈΡΡΠ΅Π·Π½Π΅Ρ.
Tagged Unions ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡ TypeScript Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΡΡ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠΉ ΡΠΈΠΏ Π²Π½ΡΡΡΠΈ ΡΡΠ»ΠΎΠ²Π½ΡΡ
Π±Π»ΠΎΠΊΠΎΠ² Π±Π»Π°Π³ΠΎΠ΄Π°ΡΡ ΡΠ²ΠΎΠΉΡΡΠ²Ρ-Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΎΡΡ. ΠΡΠΎ Π·Π°ΠΌΠ΅Π½ΡΠ΅Ρ ΡΠΈΡΠΊΠΎΠ²Π°Π½Π½ΡΠ΅ ΡΡΡΠ½ΡΠ΅ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ (as Type
) ΠΈ Π΄Π΅Π»Π°Π΅Ρ ΡΠ°Π±ΠΎΡΡ ΡΠΎ ΡΠ»ΠΎΠΆΠ½ΡΠΌΠΈ Π΄Π°Π½Π½ΡΠΌΠΈ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΠΉ.
Π IDE ΡΡΠΎ Π΄Π°ΡΡ ΡΠΎΡΠ½ΠΎΠ΅ Π°Π²ΡΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅. ΠΠ΅Π· Tagged Unions Π΄Π»Ρ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ (Dog | Cat) ΡΠ΅Π΄Π°ΠΊΡΠΎΡ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ±ΡΠΈΠ΅ ΡΠ²ΠΎΠΉΡΡΠ²Π°. Π Π°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΡ ΠΏΡΠΈΡ ΠΎΠ΄ΠΈΡΡΡ Π²ΡΡΡΠ½ΡΡ ΠΏΡΠΎΠ²Π΅ΡΡΡΡ ΡΠΈΠΏΡ, ΡΡΠΎ Π·Π°ΠΌΠ΅Π΄Π»ΡΠ΅Ρ ΡΠ°Π±ΠΎΡΡ. Π‘ Tagged Unions ΠΏΠΎΡΠ»Π΅ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΎΡΠ° TypeScript ΠΌΠ³Π½ΠΎΠ²Π΅Π½Π½ΠΎ ΡΠ°ΡΠΏΠΎΠ·Π½Π°ΡΡ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠΉ ΡΠΈΠΏ, ΠΈ IDE ΠΏΡΠ΅Π΄Π»Π°Π³Π°Π΅Ρ ΡΠΎΠ»ΡΠΊΠΎ ΡΠ΅Π»Π΅Π²Π°Π½ΡΠ½ΡΠ΅ ΡΠ²ΠΎΠΉΡΡΠ²Π°.
Π‘ΠΈΡΡΠ΅ΠΌΠ° Π±Π΅ΡΡΡ Π½Π° ΡΠ΅Π±Ρ Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π½ΠΈΠ΅ ΡΡΡΡΠΊΡΡΡ Π΄Π°Π½Π½ΡΡ , ΡΠ½ΠΈΠΆΠ°Ρ ΠΊΠΎΠ³Π½ΠΈΡΠΈΠ²Π½ΡΡ Π½Π°Π³ΡΡΠ·ΠΊΡ. ΠΡΠΎ ΡΡΠΊΠΎΡΡΠ΅Ρ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π°, ΡΠΌΠ΅Π½ΡΡΠ°Π΅Ρ ΠΎΡΠΈΠ±ΠΊΠΈ ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠΎΡΡΠ΅Π΄ΠΎΡΠΎΡΠΈΡΡΡΡ Π½Π° Π»ΠΎΠ³ΠΈΠΊΠ΅, Π° Π½Π΅ ΡΠΈΠΏΠ°Ρ .
Tagged Unions ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°ΡΡ ΡΠΈΡΡΠΎΡΡ ΠΊΠΎΠ΄Π° ΠΈ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠΉ ΡΠ΅ΡΠ°ΠΊΡΠΎΡΠΈΠ½Π³ ΡΠ΅ΡΠ΅Π· ΡΠ²Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ Π²ΡΠ΅Ρ ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ.Β Π―Π²Π½Π°Ρ ΡΡΡΡΠΊΡΡΡΠ° ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π²Π°ΡΠΈΠ°Π½ΡΠ° ΡΠΎΠ·Π΄Π°ΡΡ ΡΠ°ΠΌΠΎΠ΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠΈΡΡΡΡΡΡΡΡ ΡΠΈΡΡΠ΅ΠΌΡ ΡΠΈΠΏΠΎΠ², Π³Π΄Π΅ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΡΡΠ°Π·Ρ Π²ΠΈΠ΄ΡΡ Π΄ΠΎΠΏΡΡΡΠΈΠΌΡΠ΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ ΠΈ ΠΈΡ Π΄Π°Π½Π½ΡΠ΅. ΠΡΠΎ ΡΠ½ΠΈΠΆΠ°Π΅Ρ ΠΊΠΎΠ³Π½ΠΈΡΠΈΠ²Π½ΡΡ Π½Π°Π³ΡΡΠ·ΠΊΡ ΠΏΡΠΈ ΡΡΠ΅Π½ΠΈΠΈ ΠΊΠΎΠ΄Π° ΠΈ ΡΡΠΊΠΎΡΡΠ΅Ρ ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π»ΠΎΠ³ΠΈΠΊΠΈ Π΄Π°ΠΆΠ΅ ΡΠΏΡΡΡΡ ΠΌΠ΅ΡΡΡΡ.
ΠΡΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ TypeScript Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ Π½Π°Ρ ΠΎΠ΄ΠΈΡ Π½Π΅ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°Π½Π½ΡΠ΅ ΡΠ»ΡΡΠ°ΠΈ Π±Π»Π°Π³ΠΎΠ΄Π°ΡΡ ΠΈΡΡΠ΅ΡΠΏΡΠ²Π°ΡΡΠ΅ΠΉ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ΅. ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ Π²Π°ΡΠΈΠ°Π½ΡΠ° ΠΈΠ»ΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠ΅Π³ΠΎ Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΈΠ²Π°Π΅Ρ ΠΌΠ΅ΡΡΠ° Π΄Π»Ρ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ, ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠ°Ρ ΠΎΡΠΈΠ±ΠΊΠΈ Π΄ΠΎ Π΄Π΅ΠΏΠ»ΠΎΡ. Π‘ΠΈΡΡΠ΅ΠΌΠ° ΡΠΈΠΏΠΎΠ² ΡΡΠ°Π½ΠΎΠ²ΠΈΡΡΡ Π°ΠΊΡΠΈΠ²Π½ΡΠΌ ΡΠΎΠ°Π²ΡΠΎΡΠΎΠΌ: Π²ΠΌΠ΅ΡΡΠΎ ΡΡΡΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠΈΡΠΊΠ° Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡ Π³Π°ΡΠ°Π½ΡΠΈΡΡΠ΅Ρ, ΡΡΠΎ ΡΠ΅ΡΠ°ΠΊΡΠΎΡΠΈΠ½Π³ (ΠΏΠ΅ΡΠ΅ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½ΠΈΠ΅, ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΡΠΈΠ³Π½Π°ΡΡΡ) Π½Π΅ ΡΠ»ΠΎΠΌΠ°Π΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ.
Π’Π°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ, ΠΊΠΎΠ΄ ΡΡΡΠΎΠΉΡΠΈΠ² ΠΊ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡΠΌ Π΄Π°ΠΆΠ΅ Π² Π±ΠΎΠ»ΡΡΠΈΡ ΠΈ ΡΠ»ΠΎΠΆΠ½ΡΡ ΠΏΡΠΎΠ΅ΠΊΡΠ°Ρ , Π° ΡΠ΅ΡΠ°ΠΊΡΠΎΡΠΈΠ½Π³ ΠΏΡΠ΅Π²ΡΠ°ΡΠ°Π΅ΡΡΡ ΠΈΠ· ΡΠΈΡΠΊΠΎΠ²Π°Π½Π½ΠΎΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ Π² ΠΏΡΠ΅Π΄ΡΠΊΠ°Π·ΡΠ΅ΠΌΡΠΉ ΠΏΡΠΎΡΠ΅ΡΡ.
Π‘ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ IDE, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ Visual Studio Code, ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΡΡ Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΡΠ»ΡΡΡΠ΅Π½Π½ΠΎΠ΅ Π°Π²ΡΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΊΡ ΠΎΡΠΈΠ±ΠΎΠΊ ΠΏΡΠΈ ΡΠ°Π±ΠΎΡΠ΅ Ρ Tagged Unions. IDE ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎ Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΎΡΠ°Ρ Π΄Π»Ρ ΡΠΎΡΠ½ΡΡ ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΠΎΠΊ ΡΠ²ΠΎΠΉΡΡΠ² ΠΈ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΠ³ΠΎ ΡΠ΅ΡΠ°ΠΊΡΠΎΡΠΈΠ½Π³Π°. ΠΡΠΎ ΡΠΎΠΊΡΠ°ΡΠ°Π΅Ρ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΎΠΏΠ΅ΡΠ°ΡΠΎΠΊ ΠΈ ΡΡΠΊΠΎΡΡΠ΅Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΡ Π·Π° ΡΡΡΡ ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΉ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ ΡΠΈΠΏΠΎΠ² ΠΏΡΡΠΌΠΎ Π² ΡΠ΅Π΄Π°ΠΊΡΠΎΡΠ΅.
Tagged Unions ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΡΡ ΠΌΠΎΡΠ½ΡΠΉ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌ Π΄Π»Ρ ΡΡΡΠΎΠ³ΠΎΠ³ΠΎ ΠΌΠΎΠ΄Π΅Π»ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡΡ , ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎ ΠΊΠΎΠ³Π΄Π° ΡΠ΅ΡΡ ΠΈΠ΄ΡΡ ΠΎΠ± Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡΡ ΠΈΠ»ΠΈ ΡΠ»ΠΎΠΆΠ½ΡΡ UI-ΠΏΠ΅ΡΠ΅Ρ ΠΎΠ΄Π°Ρ . ΠΡ ΡΡΠ½Π΄Π°ΠΌΠ΅Π½ΡΠ°Π»ΡΠ½ΠΎΠ΅ ΠΏΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ²ΠΎ Π·Π°ΠΊΠ»ΡΡΠ°Π΅ΡΡΡ Π²Β ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΈ Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΈ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΡ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°ΡΠΈΠΉ ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉΒ Π½Π° ΡΡΠΎΠ²Π½Π΅ ΡΠΈΡΡΠ΅ΠΌΡ ΡΠΈΠΏΠΎΠ², ΡΡΠΎ ΠΏΡΠΈΠ½ΡΠΈΠΏΠΈΠ°Π»ΡΠ½ΠΎ ΠΎΡΠ»ΠΈΡΠ°Π΅Ρ ΡΡΠΎΡ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ ΠΎΡ ΡΡΠ°Π΄ΠΈΡΠΈΠΎΠ½Π½ΡΡ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ΠΌ.
Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ ΡΠΈΠΏΠΈΡΠ½ΡΠΉ ΡΡΠ΅Π½Π°ΡΠΈΠΉ Π·Π°Π³ΡΡΠ·ΠΊΠΈ Π΄Π°Π½Π½ΡΡ :
type LoadingState = { status: 'loading' };
type LoadedState<T> = { status: 'loaded'; data: T };
type ErrorState = { status: 'error'; message: string; errorCode?: number };
type UIState<T> = LoadingState | LoadedState<T> | ErrorState;
ΠΠ°ΠΆΠ΄ΡΠΉ Π²Π°ΡΠΈΠ°Π½Ρ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΡΠ²Π½ΡΠΉ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΡΒ status
, ΠΊΠΎΡΠΎΡΡΠΉ ΡΡΡΠΎΠ³ΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ ΡΠ²ΡΠ·Π°Π½Π½ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅Β ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ ΡΠ΅Π»Π΅Π²Π°Π½ΡΠ½ΡΡ
ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ.
Π ΡΡΠ½ΠΊΡΠΈΠΈ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π° TypeScript ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°ΡΠΎΡΒ status
Β Π΄Π»Ρ ΡΠΎΡΠ½ΠΎΠ³ΠΎ ΡΡΠΆΠ΅Π½ΠΈΡ ΡΠΈΠΏΠ°:
function renderUI<T>(state: UIState<T>): React.ReactNode {
switch (state.status) {
case 'loading':
return <Spinner />;
case 'loaded':
// TypeScript Π³Π°ΡΠ°Π½ΡΠΈΡΡΠ΅Ρ Π΄ΠΎΡΡΡΠΏ ΠΊ state.data
return <DataView content={state.data} />;
case 'error':
// ΠΠΎΡΡΡΠΏΠ½Ρ Π’ΠΠΠ¬ΠΠ ΡΠ²ΠΎΠΉΡΡΠ²Π° ErrorState
return <ErrorMessage
message={state.message}
code={state.errorCode}
/>;
default:
// ΠΠ°ΡΠΈΡΠ° ΠΎΡ Π±ΡΠ΄ΡΡΠΈΡ
ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ
const _exhaustiveCheck: never = state;
throw new Error(`Unhandled status: ${_exhaustiveCheck}`);
}
}
ΠΠ»ΡΡΠ΅Π²ΡΠ΅ ΠΏΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ²Π° ΠΏΠ΅ΡΠ΅Π΄ ΡΡΠ°Π΄ΠΈΡΠΈΠΎΠ½Π½ΡΠΌΠΈ ΠΏΠΎΠ΄Ρ ΠΎΠ΄Π°ΠΌΠΈ:
Π£ΡΡΡΠ°Π½Π΅Π½ΠΈΠ΅ ΠΏΡΠΎΡΠΈΠ²ΠΎΡΠ΅ΡΠΈΠ²ΡΡ
ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ. Π ΠΊΠ»Π°ΡΡΠΎΠ²ΡΡ
ΡΠ΅ΡΠ΅Π½ΠΈΡΡ
ΡΠ°ΡΡΠΎ Π²ΡΡΡΠ΅ΡΠ°ΡΡΡΡ ΡΠ»Π°Π³ΠΈ Π²ΡΠΎΠ΄Π΅Β isLoading
,Β isError
,Β data
, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΌΠΎΠ³ΡΡ Π½Π°Ρ
ΠΎΠ΄ΠΈΡΡΡΡ Π² ΠΏΡΠΎΡΠΈΠ²ΠΎΡΠ΅ΡΠΈΠ²ΡΡ
ΠΊΠΎΠΌΠ±ΠΈΠ½Π°ΡΠΈΡΡ
(Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ,Β isLoading=true
Β ΠΈΒ data=[...]
). Tagged Unions Π΄Π΅Π»Π°ΡΡ ΡΠ°ΠΊΠΈΠ΅ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°ΡΠΈΠΈΒ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΠΌΠΈ Π½Π° ΡΡΠΎΠ²Π½Π΅ ΡΠΈΠΏΠΎΠ²
ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠ°Ρ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΡ Π΄Π°Π½Π½ΡΡ
. ΠΡΠΈ ΡΡΠ°ΡΡΡΠ΅Β 'loading'
Β ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡ Π±Π»ΠΎΠΊΠΈΡΡΠ΅Ρ ΠΏΠΎΠΏΡΡΠΊΠΈ Π΄ΠΎΡΡΡΠΏΠ° ΠΊΒ state.data
Β ΠΈΠ»ΠΈΒ state.message
, ΡΡΠΎ ΠΎΠ±Π½Π°ΡΡΠΆΠΈΠ²Π°Π΅ΡΡΡ ΡΡΠ°Π·Ρ ΠΏΡΠΈ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΠΈ ΠΊΠΎΠ΄Π°, Π° Π½Π΅ Π² ΡΠ°Π½ΡΠ°ΠΉΠΌΠ΅.
Π‘ΠΈΠ½Ρ
ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ UI Ρ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠΎΠΉ. ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ,Β 'initial'
) Π°ΠΊΡΠΈΠ²ΠΈΡΡΠ΅Ρ ΠΎΡΠΈΠ±ΠΊΠΈ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ Π²ΠΎ Π²ΡΠ΅Ρ
ΠΌΠ΅ΡΡΠ°Ρ
ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ, Π³Π°ΡΠ°Π½ΡΠΈΡΡΡ ΡΠΎΠ³Π»Π°ΡΠΎΠ²Π°Π½Π½ΠΎΡΡΡ Π»ΠΎΠ³ΠΈΠΊΠΈ ΠΈ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°.
Tagged Unions ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡ ΡΠΈΠΏΠΎΠ±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠ΅ ΡΠΎΡΠΌΠ°ΡΡ ΠΎΡΠ²Π΅ΡΠΎΠ² ΠΎΡ ΡΠ΅ΡΠ²Π΅ΡΠ°, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΡΠΏΠ΅ΡΠ½ΡΠΉ ΠΎΡΠ²Π΅Ρ Ρ Π΄Π°Π½Π½ΡΠΌΠΈ ΠΈΠ»ΠΈ ΠΎΡΠ²Π΅Ρ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ. ΠΡΠΎ Π³Π°ΡΠ°Π½ΡΠΈΡΡΠ΅Ρ, ΡΡΠΎ Π²ΡΠ΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΠ΅ ΠΎΡΠ²Π΅ΡΡ ΠΎΡ ΡΠ΅ΡΠ²Π΅ΡΠ° (ΡΡΠΏΠ΅Ρ , ΠΎΡΠΈΠ±ΠΊΠ°) Π±ΡΠ΄ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°Π½Ρ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ.
type ApiSuccess<T> = {
Β Β response_type: 'success';
Β Β data: T;
};
type ApiError = {
Β Β response_type: 'error';
Β Β message: string;
Β Β statusCode: number;
};
type ApiResponse<T> = ApiSuccess<T> | ApiError;
async function fetchData<T>(url: string): Promise<ApiResponse<T>> {
Β Β try {
Β Β Β Β const response = await fetch(url);
Β Β Β Β if (!response.ok) {
Β Β Β Β Β Β return {
Β Β Β Β Β Β Β Β response_type: 'error',
Β Β Β Β Β Β Β Β message: `ΠΡΠΈΠ±ΠΊΠ° HTTP: ${response.statusText}`,
Β Β Β Β Β Β Β Β statusCode: response.status
Β Β Β Β Β Β };
Β Β Β Β }
Β Β Β Β const data: T = await response.json();
Β Β Β Β return { response_type: 'success', data };
Β Β } catch (error: any) {
Β Β Β Β return {
Β Β Β Β Β Β response_type: 'error',
Β Β Β Β Β Β message: error instanceof Error? error.message : 'ΠΠ΅ΠΈΠ·Π²Π΅ΡΡΠ½Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ°',
Β Β Β Β Β Β statusCode: 500
Β Β Β Β };
Β Β }
}
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅:
type UserData = { id: number; name: string; };
async function processUserResponse() { Β Β
Β Β const result = await fetchData<UserData>('/api/users/1');
Β Β if (result.response_type === 'success') {
Β Β Β Β console.log(`ΠΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ: ${result.data.name}`); // TypeScript Π·Π½Π°Π΅Ρ, ΡΡΠΎ result.data ΡΡΡΠ΅ΡΡΠ²ΡΠ΅Ρ
Β Β } else {
Β Β Β Β console.error(`ΠΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΠΈ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ: ${result.message} (ΠΠΎΠ΄: ${result.statusCode})`); // TypeScript Π·Π½Π°Π΅Ρ, ΡΡΠΎ result.message ΠΈ statusCode ΡΡΡΠ΅ΡΡΠ²ΡΡΡ
Β Β }
}
Π’Π°ΠΊΠΎΠ΅ ΠΌΠΎΠ΄Π΅Π»ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈΡΠΊΠ»ΡΡΠ°Π΅Ρ ΡΠΈΡΡΠ°ΡΠΈΠΈ, ΠΊΠΎΠ³Π΄Π° ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊ Π·Π°Π±ΡΠ²Π°Π΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°ΡΡ ΠΊΠΎΠ΄ ΠΎΡΠΈΠ±ΠΊΠΈ ΠΈΠ»ΠΈ ΠΏΡΡΠ°Π΅ΡΡΡ ΠΏΠΎΠ»ΡΡΠΈΡΡΒ data
Β ΠΏΡΠΈ ΠΎΡΠΈΠ±ΠΊΠ΅ API.
Tagged Unions ΠΈΠ΄Π΅Π°Π»ΡΠ½ΠΎ Π²ΠΎΠΏΠ»ΠΎΡΠ°ΡΡ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»ΡΠ½ΡΠ΅ ΠΊΠΎΠ½ΡΠ΅ΠΏΡΠΈΠΈ, Π³Π΄Π΅ ΠΎΡΡΡΡΡΡΠ²ΠΈΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ β ΡΠ²Π½ΠΎΠ΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΡΠΈΡΡΠ΅ΠΌΡ.
Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΠΈΠΏΠ°Β Option
Β (Π°Π½Π°Π»ΠΎΠ³Β Maybe
Β Π² Haskell) β ΡΡΠ½Π΄Π°ΠΌΠ΅Π½ΡΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠ° Π΄Π»Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ nullable-Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ Π±Π΅Π· ΡΠΈΡΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ Ρ Β undefined
/null
:
type None = { kind: "none" };
type Some<T> = { kind: "some"; value: T };
type Option<T> = None | Some<T>;
Π’ΠΈΠΏ None
Β β ΡΠ²Π½ΠΎΠ΅ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ "ΠΎΡΡΡΡΡΡΠ²ΠΈΡ Π·Π½Π°ΡΠ΅Π½ΠΈΡ" (Π±Π΅Π·Β null
!). Π’ΠΈΠΏ Some<T>
β ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅Ρ Π΄Π»Ρ ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠ΅Π³ΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΡΠΈΠΏΠ°Β T
.
ΠΡΠΈΠΌΠ΅Ρ:
const getUserName = (user: Option<User>): string => {
switch (user.kind) {
case "none":
return "ΠΠΎΡΡΡ"; // ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ Π·Π°Π³Π»ΡΡΠΊΡ ΠΊΠΎΠ³Π΄Π° Π½Π΅Ρ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ
case "some":
return user.value.name; // TypeScript Π·Π½Π°Π΅Ρ, ΡΡΠΎ user.value ΡΡΡΠ΅ΡΡΠ²ΡΠ΅Ρ
}
};
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅:
const loggedInUser: Some<User> = {
kind: "some",
value: {
name: "ΠΠ²Π°Π½"
}
};
const guestUser: None = { kind: "none" };
getUserName(loggedInUser); // "ΠΠ²Π°Π½"
getUserName(guestUser); // "ΠΠΎΡΡΡ"
Π’Π°ΠΊ ΠΆΠ΅ ΡΠ°ΡΡΠΌΠΎΡΡΠΈΠΌ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΠΈΠΏΠ° Result
. ΠΠ½ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅Ρ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ Π»ΠΈΠ±ΠΎ ΡΡΠΏΠ΅Ρ
ΠΎΠΌ (Success<T>
) Ρ Π΄Π°Π½Π½ΡΠΌΠΈ, Π»ΠΈΠ±ΠΎ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ (Failure<E>
) Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠ΅ΠΉ ΠΎΠ± ΠΎΡΠΈΠ±ΠΊΠ΅. Π ΠΎΡΠ»ΠΈΡΠΈΠ΅ ΠΎΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ,Β Result
Β Π΄Π΅Π»Π°Π΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ ΠΎΡΠΈΠ±ΠΎΠΊ ΡΠ²Π½ΠΎΠΉ ΠΈ ΡΠΈΠΏΠΎΠ±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΠΉ.
type Success<T> = { status: 'success'; data: T; };
type Failure<E> = { status: 'failure'; error: E; };
type Result<T, E> = Success<T> | Failure<E>;
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅:
function parseNumber(input: string): Result<number, string> {
Β Β const num = parseInt(input);
Β Β if (isNaN(num)) {
Β Β Β Β return { status: 'failure', error: `ΠΠ΅Π²Π΅ΡΠ½ΡΠΉ Π²Π²ΠΎΠ΄: "${input}" Π½Π΅ ΡΠ²Π»ΡΠ΅ΡΡΡ ΡΠΈΡΠ»ΠΎΠΌ.` };
Β Β }
Β Β return { status: 'success', data: num };
}
const parsed = parseNumber('123');
if (parsed.status === 'success') {
Β Β console.log(`ΠΠ°ΡΡΠΈΠ½Π³ ΡΡΠΏΠ΅ΡΠ΅Π½: ${parsed.data}`);
} else {
Β Β console.error(`ΠΡΠΈΠ±ΠΊΠ° ΠΏΠ°ΡΡΠΈΠ½Π³Π°: ${parsed.error}`);
}
ΠΠΈΡΠΊΡΠΈΠΌΠΈΠ½ΠΈΡΡΠ΅ΠΌΡΠ΅ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Π² TypeScript ΡΠ²Π»ΡΡΡΡΡ ΡΡΠ½Π΄Π°ΠΌΠ΅Π½ΡΠ°Π»ΡΠ½ΡΠΌ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠΌ Π΄Π»Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ Π½Π°Π΄Π΅ΠΆΠ½ΡΡ , ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΡΠ΅ΠΌΡΡ ΠΈ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ. ΠΠ½ΠΈ ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΡΡ ΠΌΠΎΡΠ½ΡΠΉ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌ Π΄Π»Ρ ΠΌΠΎΠ΄Π΅Π»ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΡΠ»ΠΎΠΆΠ½ΡΡ ΡΡΡΡΠΊΡΡΡ Π΄Π°Π½Π½ΡΡ , ΠΊΠΎΡΠΎΡΡΠ΅ ΠΌΠΎΠ³ΡΡ ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠ΅, Π½ΠΎ ΠΏΡΠΈ ΡΡΠΎΠΌ ΡΠΈΠΊΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΡΠΎΡΠΌΡ, ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°Ρ Π²ΡΡΠΎΠΊΡΡ ΡΡΠ΅ΠΏΠ΅Π½Ρ ΡΠΈΠΏΠΎΠ±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ ΠΈ ΠΏΡΠ΅Π΄ΡΠΊΠ°Π·ΡΠ΅ΠΌΠΎΡΡΠΈ ΠΊΠΎΠ΄Π°.
ΠΠ°ΠΊ Π±ΡΠ»ΠΎ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ, Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½ΠΈΡΡΠ΅ΠΌΡΠ΅ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΡΠ»ΡΡΡΠ°ΡΡ ΡΠΈΠΏΠΎΠ±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΡ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡΡ Π²ΡΡΠ²Π»ΡΡΡ ΠΎΡΠΈΠ±ΠΊΠΈ Π½Π° ΡΡΠ°ΠΏΠ΅ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ ΠΈ Π³Π°ΡΠ°Π½ΡΠΈΡΡΡ, ΡΡΠΎ Π²ΡΠ΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΠ΅ Π²Π°ΡΠΈΠ°Π½ΡΡ Π΄Π°Π½Π½ΡΡ
ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΡΡ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎ. ΠΠ½ΠΈ ΠΏΠΎΠ²ΡΡΠ°ΡΡ ΡΠΈΡΠ°Π΅ΠΌΠΎΡΡΡ ΠΈ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΠΌΠΎΡΡΡ ΠΊΠΎΠ΄Π° Π·Π° ΡΡΠ΅Ρ ΡΠ²Π½ΠΎΠ³ΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ ΡΠΎΡΠΌ Π΄Π°Π½Π½ΡΡ
ΠΈ ΡΠΏΡΠΎΡΠ΅Π½ΠΈΡ ΡΡΠ»ΠΎΠ²Π½ΠΎΠΉ Π»ΠΎΠ³ΠΈΠΊΠΈ. ΠΡΠΎΠΌΠ΅ ΡΠΎΠ³ΠΎ, ΡΠ°ΠΊΠΈΠ΅ ΠΏΡΠΎΠ΄Π²ΠΈΠ½ΡΡΡΠ΅ ΡΠ΅Ρ
Π½ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ ΠΈΡΡΠ΅ΡΠΏΡΠ²Π°ΡΡΠ°Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΡΠΈΠΏΠ° never
, Π΄Π΅Π»Π°ΡΡ ΠΊΠΎΠ΄ Π±ΠΎΠ»Π΅Π΅ Π½Π°Π΄Π΅ΠΆΠ½ΡΠΌ, ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠ°Ρ ΠΏΡΠΎΠΏΡΡΠ΅Π½Π½ΡΠ΅ ΡΡΠ΅Π½Π°ΡΠΈΠΈ.
ΠΠ½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅ Tagged Unions Π² Π²Π°ΡΡ ΠΏΠΎΠ²ΡΠ΅Π΄Π½Π΅Π²Π½ΡΡ ΠΏΡΠ°ΠΊΡΠΈΠΊΡ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ Π½Π° TypeScript β ΡΡΠΎ ΠΈΠ½Π²Π΅ΡΡΠΈΡΠΈΡ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²ΠΎ ΠΊΠΎΠ΄Π°, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΌΠ½ΠΎΠ³ΠΎΠΊΡΠ°ΡΠ½ΠΎ ΠΎΠΊΡΠΏΠ°Π΅ΡΡΡ ΡΠ½ΠΈΠΆΠ΅Π½ΠΈΠ΅ΠΌ Π·Π°ΡΡΠ°Ρ Π½Π° ΠΎΡΠ»Π°Π΄ΠΊΡ, ΡΡΠΊΠΎΡΠ΅Π½ΠΈΠ΅ΠΌ ΡΠ΅ΡΠ°ΠΊΡΠΎΡΠΈΠ½Π³Π° ΠΈ ΠΏΠΎΠ²ΡΡΠ΅Π½ΠΈΠ΅ΠΌ ΡΡΠ°Π±ΠΈΠ»ΡΠ½ΠΎΡΡΠΈ Π²Π°ΡΠ΅Π³ΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ. ΠΠΎΠ΄Π΅Π»ΠΈΡΠ΅ΡΡ ΡΠ²ΠΎΠΈΠΌ ΠΎΠΏΡΡΠΎΠΌ Π² ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΡΡ β Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Ρ Π²Π°Ρ Π΅ΡΡΡ ΡΠ²ΠΎΠΈ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΠ΅ ΡΡΠ΅Π½Π°ΡΠΈΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Tagged Unions!