Φτιάξτε ένα αντικείμενο συνάρτηση με ακίνητα στη γραφομηχανή

ψήφοι
46

Θέλω να δημιουργήσω ένα αντικείμενο λειτουργία, η οποία επίσης έχει κάποιες ιδιότητες που πραγματοποιήθηκε σε αυτό. Για παράδειγμα σε JavaScript θα ήθελα να κάνω:

var f = function() { }
f.someValue = 3;

Τώρα με γραφομηχανή μπορώ να περιγράψω το είδος του, όπως:

var f: { (): any; someValue: number; };

Ωστόσο, δεν μπορώ να το χτίσει στην πραγματικότητα, χωρίς να απαιτείται καστ. Οπως:

var f: { (): any; someValue: number; } =
    <{ (): any; someValue: number; }>(
        function() { }
    );
f.someValue = 3;

Πώς θα οικοδομήσουμε αυτό χωρίς ένα cast;

Δημοσιεύθηκε 07/10/2012 στις 07:08
πηγή χρήστη
Σε άλλες γλώσσες...                            


9 απαντήσεις

ψήφοι
73

Ενημέρωση: Η απάντηση ήταν η καλύτερη λύση σε παλαιότερες εκδόσεις του γραφομηχανή, αλλά υπάρχουν καλύτερες επιλογές που είναι διαθέσιμες σε νεότερες εκδόσεις (δείτε άλλες απαντήσεις).

Η αποδεκτή απάντηση εργάζεται και μπορεί να απαιτείται σε ορισμένες περιπτώσεις, αλλά έχουν το μειονέκτημα να παρέχει καμία ασφάλεια τύπων για τη δημιουργία του αντικειμένου. Η τεχνική αυτή θα πρέπει τουλάχιστον να ρίξει ένα σφάλμα τύπου, εάν προσπαθήσετε να προσθέσετε μια απροσδιόριστη ιδιότητα.

interface F { (): any; someValue: number; }

var f = <F>function () { }
f.someValue = 3

// type error
f.notDeclard = 3
Απαντήθηκε 05/09/2013 στις 16:12
πηγή χρήστη

ψήφοι
34

Γραφομηχανή έχει σχεδιαστεί για να χειριστεί την υπόθεση με τη δήλωση συγχώνευση :

μπορεί επίσης να είναι εξοικειωμένοι με την πρακτική το JavaScript τη δημιουργία μιας λειτουργίας και, στη συνέχεια, για την παράταση της λειτουργίας περαιτέρω προσθέτοντας ιδιότητες πάνω στο λειτουργία. Γραφομηχανή χρησιμοποιεί δήλωση συγχώνευση για τη δημιουργία ορισμών όπως αυτό σε ένα τύπου ασφαλή τρόπο.

Δήλωση συγχώνευση μας επιτρέπει να πούμε ότι κάτι είναι και μια λειτουργία και namespace (εσωτερική μονάδα):

function f() { }
namespace f {
    export var someValue = 3;
}

Αυτό διατηρεί την πληκτρολόγηση και μας επιτρέπει να γράψει τόσο f()και f.someValue. Όταν γράφετε ένα .d.tsαρχείο για τα υπάρχοντα κώδικα JavaScript, χρησιμοποιήστε declare:

declare function f(): void;
declare namespace f {
    export var someValue: number;
}

Προσθέτοντας ιδιότητες λειτουργίες είναι συχνά μια σύγχυση ή απροσδόκητη μοτίβο στη γραφομηχανή, ώστε να προσπαθήσουμε να το αποφύγουμε, αλλά μπορεί να χρειαστεί κατά τη χρήση ή τη μετατροπή παλαιότερο κώδικα JS. Αυτό είναι ένα από τα μόνα φορές θα ήταν σκόπιμο να αναμειγνύεται εσωτερικές μονάδες (namespaces) με εξωτερικούς.

Απαντήθηκε 28/10/2015 στις 13:47
πηγή χρήστη

ψήφοι
27

Αυτό είναι εύκολα εφικτό σήμερα (γραφομηχανή 2.x) με Object.assign(target, source)

παράδειγμα:

εισάγετε περιγραφή της εικόνας εδώ

Η μαγεία εδώ είναι ότι Object.assign<T, U>(...)είναι δακτυλογραφημένα να επιστρέψει μια διασταύρωση τύπο της T & U.

Επιβολή ότι αυτό επιλύει σε ένα γνωστό περιβάλλον εργασίας είναι επίσης απλός:

interface Foo {
  (a: number, b: string): string[];
  foo: string;
}

let method: Foo = Object.assign(
  (a: number, b: string) => { return a * a; },
  { foo: 10 }
); 

Σφάλμα: foo: αριθμός δεν εντάσσονται σε foo: συμβολοσειρά
Σφάλμα: αριθμός δεν εντάσσονται σε string [] (τύπος επιστροφής)

προειδοποίηση: μπορεί να χρειαστεί να polyfill Object.assign αν στόχευσης παλαιότερα προγράμματα περιήγησης.

Απαντήθηκε 25/01/2017 στις 13:43
πηγή χρήστη

ψήφοι
17

Έτσι, αν η απαίτηση είναι απλά να δημιουργήσει και να αναθέσει τη λειτουργία αυτή για να «f» χωρίς καστ, εδώ είναι μια πιθανή λύση:

var f: { (): any; someValue: number; };

f = (() => {
    var _f : any = function () { };
    _f.someValue = 3;
    return _f;
})();

Ουσιαστικά, χρησιμοποιεί μια λειτουργία εκτέλεση εαυτό κυριολεκτική να «κατασκευάσει» ένα αντικείμενο που θα ταιριάζει με αυτή την υπογραφή, πριν γίνει η ανάθεση. Η μόνη παραξενιά είναι ότι η εσωτερική δήλωση της συνάρτησης πρέπει να είναι του τύπου «κάθε», διαφορετικά ο compiler φωνάζει ότι είστε ανάθεση σε ένα ακίνητο το οποίο δεν υπάρχει στο αντικείμενο ακόμα.

EDIT: Απλοποιημένη ο κωδικός λίγο.

Απαντήθηκε 07/10/2012 στις 17:33
πηγή χρήστη

ψήφοι
1

Δεν μπορώ να πω ότι είναι πολύ απλό, αλλά είναι σίγουρα δυνατό:

interface Optional {
  <T>(value?: T): OptionalMonad<T>;
  empty(): OptionalMonad<any>;
}

const Optional = (<T>(value?: T) => OptionalCreator(value)) as Optional;
Optional.empty = () => OptionalCreator();

αν έχεις περίεργο αυτό είναι από την ουσία μου με την έκδοση γραφομηχανή / JavaScript τουOptional

Απαντήθηκε 07/02/2018 στις 23:57
πηγή χρήστη

ψήφοι
1

Μια ενημερωμένη απάντηση: μετά την προσθήκη των τύπων τομής μέσω &, είναι δυνατόν να «συγχώνευση» δύο συναχθεί τύπους on the fly.

Εδώ είναι μια γενική βοηθός που διαβάζει τις ιδιότητες κάποιου αντικειμένου fromκαι των αντιγράφων τους πάνω από ένα αντικείμενο onto. Επιστρέφει το ίδιο αντικείμενο onto, αλλά με ένα νέο τύπο που περιλαμβάνει δύο σύνολα των ακινήτων, τόσο σωστά περιγράφει τη συμπεριφορά χρόνου εκτέλεσης:

function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
    Object.keys(from).forEach(key => onto[key] = from[key]);
    return onto as T1 & T2;
}

Αυτό το βοηθητικό χαμηλού επιπέδου έχει ακόμη εκτελέσει τύπου ισχυρισμό, αλλά είναι τύπου ασφαλές από το σχεδιασμό. Με αυτό το βοηθητικό στη θέση του, έχουμε ένα φορέα που μπορούμε να χρησιμοποιήσουμε για να λύσει το πρόβλημα του Ε.Π., με πλήρη ασφάλεια τύπο:

interface Foo {
    (message: string): void;
    bar(count: number): void;
}

const foo: Foo = merge(
    (message: string) => console.log(`message is ${message}`), {
        bar(count: number) {
            console.log(`bar was passed ${count}`)
        }
    }
);

Κάντε κλικ εδώ για να το δοκιμάσετε στο γραφομηχανή χαρά . Σημειώστε ότι έχουμε περιορίζεται fooνα είναι του τύπου Foo, έτσι ώστε το αποτέλεσμα mergeπρέπει να είναι πλήρης Foo. Έτσι, αν μετονομάσετε barσε badσυνέχεια μπορείτε να πάρετε ένα σφάλμα τύπου.

Σημείωση: Υπάρχει ακόμα μια τρύπα τύπο εδώ, όμως. Γραφομηχανή δεν παρέχει έναν τρόπο για να περιορίσουν μια παράμετρο τύπου να είναι «δεν είναι μια λειτουργία». Έτσι, μπορείτε να μπερδευτείτε και να περάσει τη λειτουργία σας ως το δεύτερο επιχείρημα merge, και αυτό δεν θα μπορούσε να λειτουργήσει. Έτσι, μέχρι αυτό μπορεί να δηλωθεί, θα πρέπει να το πιάσει κατά το χρόνο εκτέλεσης:

function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
    if (typeof from !== "object" || from instanceof Array) {
        throw new Error("merge: 'from' must be an ordinary object");
    }
    Object.keys(from).forEach(key => onto[key] = from[key]);
    return onto as T1 & T2;
}
Απαντήθηκε 10/03/2016 στις 19:14
πηγή χρήστη

ψήφοι
1

Ως συντόμευση, μπορείτε δυναμικά να ορίσετε την τιμή του αντικειμένου με τη χρήση του [ «ιδιοκτησίας»] accessor:

var f = function() { }
f['someValue'] = 3;

Αυτό παρακάμπτει τον έλεγχο του τύπου. Ωστόσο, είναι αρκετά ασφαλές γιατί πρέπει να σκόπιμα την πρόσβαση στην ιδιοκτησία με τον ίδιο τρόπο:

var val = f.someValue; // This won't work
var val = f['someValue']; // Yeah, I meant to do that

Ωστόσο, εάν θέλετε πραγματικά το είδος ελέγχου για την αξία του ακινήτου, αυτό δεν θα λειτουργήσει.

Απαντήθηκε 11/10/2012 στις 05:38
πηγή χρήστη

ψήφοι
0

Παλιά ερώτηση, αλλά για τις εκδόσεις της γραφομηχανή ξεκινώντας με 3.1, μπορείτε απλά να κάνετε την εκχώρηση ακινήτου, όπως θα κάνατε σε απλό JS, εφ 'όσον χρησιμοποιείτε μια δήλωση λειτουργία ή τη constλέξη-κλειδί για τη μεταβλητή σας:

function f () {}
f.someValue = 3; // fine
const g = function () {};
g.someValue = 3; // also fine
var h = function () {};
h.someValue = 3; // Error: "Property 'someValue' does not exist on type '() => void'"

Αναφορά και στο διαδίκτυο παράδειγμα .

Απαντήθηκε 26/11/2018 στις 21:38
πηγή χρήστη

ψήφοι
0

Αυτό αναχωρεί από την ισχυρή πληκτρολόγηση, αλλά μπορείτε να το κάνετε

var f: any = function() { }
f.someValue = 3;

εάν προσπαθείτε να πάρετε γύρω από καταπιεστικές ισχυρή δακτυλογράφηση, όπως ήμουν όταν βρήκα αυτό το ερώτημα. Δυστυχώς πρόκειται για μια περίπτωση γραφομηχανή αποτυγχάνει σε απόλυτα έγκυρη την Javascript έτσι πρέπει να σας πω γραφομηχανή για να κάνει πίσω.

«Θα την Javascript είναι απόλυτα έγκυρη γραφομηχανή» ψευδής. (Σημείωση: χρησιμοποιώντας 0.95)

Απαντήθηκε 21/02/2014 στις 16:59
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more