2015-07-16 4 views
62

Существует ли канонический способ поиска объекта в массиве с помощью TypeScript?Найти объект в массиве с использованием TypeScript

Я знаю, машинопись реализовано множество функций ES6 и ES6 могут сделать это:

[{"id":1}, {"id":-2}, {"id":3}].find(myObj => myObj.id < 0)  

// returns {"id":-2} 

Однако я не могу видеть, найти на TS roadmap.

Очевидно, это может быть сделано старомодным способом с помощью ES5 Javascript. Дело в том, что TypeScript отслеживает функции ES6, поэтому я спрашиваю, возможен ли лучший способ, желательно что-то вроде примера ES6, показанного выше.

+4

А какой объект? Я не вижу здесь примера. Кроме того, TypeScript является просто аннотированным JS. Вы можете написать vanilla JS в TypeScript, и он все равно будет работать. – Joseph

+1

@Joseph the Dreamer Обновленный пример, показывающий поиск собственных объектов JS. Я знаю, что TS поддерживает ES5-код, дело в том, что пример из ES6 намного приятнее, и TS предположительно находится на пути реализации функций ES6. – Lee

ответ

59

Часть первая - Polyfill

Для браузеров, которые не реализовали, а polyfill для array.find. Courtesy of MDN.

if (!Array.prototype.find) { 
    Array.prototype.find = function(predicate) { 
    if (this == null) { 
     throw new TypeError('Array.prototype.find called on null or undefined'); 
    } 
    if (typeof predicate !== 'function') { 
     throw new TypeError('predicate must be a function'); 
    } 
    var list = Object(this); 
    var length = list.length >>> 0; 
    var thisArg = arguments[1]; 
    var value; 

    for (var i = 0; i < length; i++) { 
     value = list[i]; 
     if (predicate.call(thisArg, value, i, list)) { 
     return value; 
     } 
    } 
    return undefined; 
    }; 
} 

Часть вторая - Интерфейс

Вам необходимо расширить открытый интерфейс массива включить метод find.

interface Array<T> { 
    find(predicate: (search: T) => boolean) : T; 
} 

Когда это прибывает в TypeScript, вы получите предупреждение от компилятора, который напомнит вам об этом.

Часть третья - Используйте его

Переменная x будет иметь ожидаемый тип ... { id: number }

var x = [{ "id": 1 }, { "id": -2 }, { "id": 3 }].find(myObj => myObj.id < 0); 
+3

Не должно быть определения типа: 'find (предикат: (T) => boolean): T;'?Если он возвращает 'Array ', то 'filter' можно использовать – Brocco

+0

@Steve Fenton красивый ответ спасибо. Пожалуйста, подумайте над тем, чтобы решить вопрос, потому что я думаю, что контент полезен, но некоторые голеностопные судороги опущены, прежде чем я смогу прояснить. – Lee

+0

Используйте 'find (предикат: (значение: T) => boolean): T;' в интерфейсе для получения безопасности типа в предикате –

9

Для некоторых проектов это проще установить цель es6 в вашем tsconfig.json.

{ 
    "compilerOptions": { 
    "target": "es6", 
    ... 
+5

Обратите внимание, что это сломает старые браузеры. – cederlof

13

Игра с tsconfig.json Вы также можете нацеливание ES5 так:

{ 
    "compilerOptions": { 
     "experimentalDecorators": true, 
     "module": "commonjs", 
     "target": "es5" 
    } 
    ... 
+4

Array.prototype.find рано заканчивается после первого правдивого возврата итерации (читайте: как только элемент найден). Это потенциально очень неэффективное решение, в зависимости от размера массив – Andrew

+0

Вы не читали все сообщения, там я просто разрешаю то, на что вы должны сосредоточиться. – everblack

-1

Вы можете просто использовать библиотеку подчеркиванием.

Установите его:

npm install underscore --save 
    npm install @types/underscore --save-dev 

Импорт он

import _ = require('underscore'); 

Используйте его

var x = _.filter(
     [{ "id": 1 }, { "id": -2 }, { "id": 3 }], 
     myObj => myObj.id < 0) 
    ); 
-1

Если вам нужны некоторые улучшения ES6 не поддерживаются машинопись, вы можете ориентировать ES6 в вашем TSconfig и использовать Babel для преобразования ваших файлов в es5.

+0

Downvoting потому что '.find' является добавлением API, поэтому добавление другого транспилера уникально бесполезно. –

+0

Он работает с babel- polyfill. Но вы правы, babel не делает это изначально с помощью пресетов. см. https://stackoverflow.com/a/32443652/7478972 –

Смежные вопросы