2017-05-01 7 views
13

Warum hat Typoskript einen Typ und dann einen "ähnlichen Typ"? Ein Beispiel dafür ist Promise<T> und PromiseLike<T>. Was sind die Unterschiede zwischen diesen beiden Arten? Wann sollte ich sie benutzen? Warum haben Sie nicht einfach einen Promise Typ?Warum verwendet Typoskript "Like" -Typen?

+0

Was würdest du antworten, wenn ich dich nach Arrays und ArrayLike-Objekten frage und wie sie sich unterscheiden? – Thomas

+1

Haben Sie sich die [Definition in der lib] (https://github.com/Microsoft/TypeScript/blob/master/lib/lib.es6.d.ts#L1323) angesehen? –

+0

Danke für den Link.Es ist gut, die definierten Typen zu sehen, jedoch konzentriert sich diese Frage mehr auf den semantischen Unterschied zwischen den beiden Typen als nur auf ihre Schnittstellen. Welchen Zweck haben diese beiden Typen? Warum hat der Autor das gewählt? Ich denke, @Thomas weist darauf hin, dass es orthogonale API-Designkonnotationen gibt. Was sind Sie? Eine Antwort, die einige dieser größeren Designfragen behandelt, ist, wonach ich suche. Ich kann den Wortlaut der Frage aktualisieren, wenn Sie möchten. – Stewart

Antwort

16

Wenn Sie sich die Definitionsdateien anschauen (nehmen wir lib.es6.d.ts), dann ist es ziemlich einfach.

Zum Beispiel der ArrayLike Schnittstelle:

interface ArrayLike<T> { 
    readonly length: number; 
    readonly [n: number]: T; 
} 

ist begrenzter als die Array ein:

interface Array<T> { 
    length: number; 
    toString(): string; 
    toLocaleString(): string; 
    push(...items: T[]): number; 
    pop(): T | undefined; 
    concat(...items: T[][]): T[]; 
    concat(...items: (T | T[])[]): T[]; 
    join(separator?: string): string; 
    reverse(): T[]; 
    shift(): T | undefined; 
    slice(start?: number, end?: number): T[]; 
    sort(compareFn?: (a: T, b: T) => number): this; 
    splice(start: number, deleteCount?: number): T[]; 
    splice(start: number, deleteCount: number, ...items: T[]): T[]; 
    unshift(...items: T[]): number; 
    indexOf(searchElement: T, fromIndex?: number): number; 
    lastIndexOf(searchElement: T, fromIndex?: number): number; 

    // lots of other methods such as every, forEach, map, etc 

    [n: number]: T; 
} 

Es ist gut, die beide getrennt zu haben, weil ich eine Funktion wie diese haben möchte:

function getSize(arr: Array<any>): number { 
    return arr.length; 
} 

console.log(getSize([1, 2, 3])); // works 

Aber es wird damit nicht funktionieren:

function fn() { 
    console.log(getSize(arguments)); // error 
} 

Es ergibt sich mit diesem Fehler:

Argument of type 'IArguments' is not assignable to parameter of type 'any[]'.
Property 'push' is missing in type 'IArguments'.

Aber beide funktioniert, wenn ich dies tun:

function getSize(arr: ArrayLike<any>): number { 
    return arr.length; 
} 

(mehr auf ArrayLike in MDN)

das gleiche mit Promise und PromiseLike, wenn ich eine Bibliothek baue, die nicht über das Implementiert ist entation der Promise dann statt, dies zu tun:

function doSomething(promise: Promise<any>) { ... } 

Ich werde dies tun:

function doSomething(promise: PromiseLike<any>) { ... } 

Dann auch wenn der Benutzer meiner Bibliothek ist eine andere Implementierung mit (drossel) wird es funktionieren fein. diese

Wenn Sie die Definition von Promise auffallen wird, ist:

declare var Promise: PromiseConstructor; 

die es sehr spezifisch, andere Implementierungen macht möglicherweise unterschiedliche Eigenschaften aufweisen, beispielsweise einen anderen Prototyp:

interface PromiseConstructor { 
    readonly prototype: Promise<any>; 

    ... 
} 

I Erraten Sie, dass der Hauptgrund, warum wir PromiseLike haben, dass mehrere Implementierungen verfügbar waren, bevor die native unterstützt wurde (wie bluebird, Promises/A+, jQuery und mehr).
Damit Typoskript mit Codebasen arbeiten kann, die diese Implementierungen verwenden, muss ein anderer Typ als Promise vorhanden sein, andernfalls gäbe es viele Widersprüche.

+0

Große Antwort, aber in diesem speziellen Fall bin ich immer noch verwirrt. Warum sollte es ein Problem geben, 'catch()' in 'PromiseLike' zu ​​haben? – rekire

+0

@rekire Ich weiß nicht, warum sie nur '' '' in 'PromiseLike' ausgewählt haben, aber ich vermute, dass einige vielversprechende Implementierungen nicht' catch' haben (zum Beispiel sieht es wie [Promises/A +] aus (https: // promisesaplus.com/) nicht). –

Verwandte Themen