Πολλές φορές χρειάζεται να είμαστε σε θέση να διαφοροποιήσουμε τις διεπαφές Typescript που έχουν κάποιες κοινές ιδιότητες. Πάρτε το ακόλουθο παράδειγμα:
interface Vehicle { weight: number; wheels?: number; class?: 'A' | '1' | '2' | '3';
}
Στην εφαρμογή μας έχουμε διαφορετικά οχήματα. Για τα φορτηγά, για παράδειγμα, θέλουμε να παρακολουθούμε το βάρος τους και τον αριθμό των τροχών τους. Ωστόσο, άλλα οχήματα (όπως γιάτς) δεν έχουν τροχούς, αλλά έχουν άλλα χαρακτηριστικά που θέλουμε να γνωρίζουμε, όπως για παράδειγμα η κατηγορία τους, η οποία είναι μια συμβολοσειρά που μπορεί να λάβει τιμές 'A', '1', '2' ή '3' .
Μπορεί να πιστεύουμε ότι μια καλή διαμόρφωση μπορεί να είναι η εξής:
interface Truck { weight: number; wheels: number;
} interface Yatch { weight: number; class: 'A' | '1' | '2' | '3';
} export type Vehicle = Truck | Yatch;
Ωστόσο, με αυτήν τη ρύθμιση θα έχουμε πρόβλημα κατά την προσπάθεια χρήσης Vehicle
αντικείμενα:
Όπως μπορούμε να δούμε, το Typescript δεν μπορεί να αποφασίσει εάν το αντικείμενο εισόδου είναι a Truck
ή ένα Yatch
και βγάζει το ακόλουθο σφάλμα:
Property 'wheels' does not exist on type 'Yatch'
Πώς μπορούμε να περιορίσουμε τον τύπο του αντικειμένου; Υπάρχουν τουλάχιστον 3 εναλλακτικές:
1. Δημιουργήστε ένα νέο type
ιδιοκτησία σε καθεμία από τις διεπαφές
interface Truck { weight: number; wheels: number; type: 'truck';
} interface Yatch { weight: number; class: 'A' | '1' | '2' | '3'; type: 'yatch';
} export type Vehicle = Truck | Yatch;
Αυτό είναι γνωστό ως διακρίνονται συνδικάτα σε γραφομηχανή. Αυτή η λύση θα ήταν η πιο κατάλληλη εάν οι διεπαφές μας είχαν ήδη το type
αποδώσει εκ των προτέρων.
Οταν χρησιμοποιείτε Vehicle
αντικείμενα, τώρα μπορούμε να χρησιμοποιήσουμε μια θήκη διακόπτη για να διαφοροποιήσουμε και τις δύο διεπαφές:
Εάν χρησιμοποιούμε κλάσεις αντί για διεπαφές για τους τύπους μας, η ακόλουθη εναλλακτική σύνταξη παράγει το ίδιο ακριβώς αποτέλεσμα:
class Truck { weight: number; wheels: number; readonly type = 'truck';
} class Yatch { weight: number; class: 'A' | '1' | '2' | '3'; readonly type = 'yatch';
} export type Vehicle = Truck | Yatch;
2. Χρησιμοποιήστε προστατευτικά τύπου
Τύπου φύλακες είναι συναρτήσεις που βοηθούν στη στένωση τύπου.
interface Truck { weight: number; wheels: number;
} interface Yatch { weight: number; class: 'A' | '1' | '2' | '3';
} export type Vehicle = Truck | Yatch; export function isTruck(arg: any): arg is Truck { return !!arg.weight && !!arg.wheels;
} export function isYatch(arg: any): arg is Yatch { return !!arg.weight && !!arg.class;
}
If isTruck(object)
Επιστροφές true
, σημαίνει ότι το αντικείμενο μας είναι όντως α Truck
. Μπορούμε να εισάγουμε και να χρησιμοποιήσουμε αυτές τις λειτουργίες οπουδήποτε στην εφαρμογή μας:
Ωστόσο, υπάρχει ένα μικρό πρόβλημα με αυτήν τη ρύθμιση: μπορούμε ακόμα να δημιουργήσουμε Vehicle
αντικείμενα που δεν είναι Truck
ούτε Yatch
:
3. Χρησιμοποιήστε «ποτέ»
Για να επιλύσουμε αυτό το τελευταίο πρόβλημα μπορούμε να χρησιμοποιήσουμε ο never
τύπου, που εισήχθη στο Typescript 2.0. Εάν μια διεπαφή έχει μια ιδιότητα τύπου never
, τότε αυτή η ιδιότητα δεν μπορεί να οριστεί σε οποιοδήποτε αντικείμενο που ακολουθεί αυτή τη διεπαφή.
interface Truck { weight: number; wheels: number; class?: never;
} interface Yatch { weight: number; wheels?: never; class: 'A' | '1' | '2' | '3';
} export type Vehicle = Truck | Yatch;
Οι φύλακες τύπου λειτουργούν ακριβώς όπως έκαναν στο παρελθόν, αλλά τώρα δεν μπορούμε να δημιουργήσουμε Vehicle
αντικείμενα που έχουν ταυτόχρονα και τα δύο wheels
και class
ιδιότητες:
Όπως μπορούμε να δούμε λαμβάνουμε το ακόλουθο σφάλμα:
Type 'number' is not assignable to type 'never'
Ελέγξτε την ισπανική έκδοση αυτής της ανάρτησης στο ιστολόγιό μου cibetrucos.com
Πηγή: https://www.codementor.io/davidsilvasanmartin/typescript-discriminated-unions-1jhqp24mvx