У меня есть функция, которая сортирует N массивов на основе первого:
export function sortArraysTogether<T>(
arrays: T[][],
comparator = (a, b) => (a < b ? -1 : a > b ? 1 : 0)
): T[][] {
Итак ([[20, 10, 30], ['bob', 'alice', 'charlie']]) ⇒ [[10, 20, 30], ['alice', 'bob', 'charlie']]
Проблема в том, что массивы, которые я передаю, относятся к разным типам, поэтому TS в данном случае жалуется, что Number[] is not assignable to string[]
Как исправить T или, скорее, сопоставить тип возвращаемого значения?
Ищете порядок, который нужно сохранить, поэтому приведенное выше должно возвращать эквивалент [number[], string[]]
(см. предыдущий комментарий). Кроме того, из этого примера неясно, беспокоят ли вас ошибки в sortArr([]) (нет первого массива) или в sortArr([[2, 1], []]) (массивы имеют несовпадающую длину), или вам нужен возвращаемый тип для отслеживания порядка, поэтому sortArr([[2,1],["a","b"],[true, false]]) возвращается (number | string | boolean)[][] или если вернется [number[], string[], boolean[]]. Это имеет значение?
T extends any[] кажется именно тем, что мне нужно (думаю; я сейчас разговариваю по телефону, но мне бы хотелось, чтобы порядок сохранялся, а не возвращался тип объединения), спасибо :) Несовпадения длин на самом деле не применяются в TS, поэтому я в таком случае я бросаю. По сути, я просто хочу, чтобы тип «прошел», без изменений.
«Несоответствия длины на самом деле не подлежат принудительному исполнению» Кортежи существуют в TS, поэтому несоответствия длины подлежат принудительному исполнению, см. эту ссылку, когда эта информация сохранена. Что нам здесь делать? Кажется, что вы в основном ищете только T extends any[], но вы также говорите, что порядок должен быть сохранен, а для этого требуются сопоставленные типы. Есть разные способы сделать это в зависимости от ваших потребностей. Пожалуйста, просмотрите различные ссылки на игровые площадки, когда доберетесь до компьютера, и дайте мне знать, как вы хотите действовать.
На самом деле, глядя на .dts, а это единственное, что я могу делать на своем телефоне, кажется, что конкретные типы теряются. Есть ли способ сохранить порядок? Надеюсь, не перегружая подпись массивами 1..10.
Соответствие длин массивов не является обязательным, например. если бы я получил массивы из вызова API неизвестной длины. Кортежи — это подмножество массивов;)
Возможно, когда вы доберетесь до настоящего компьютера, вы сможете просмотреть мои ссылки на игровую площадку (например, вот эта , которая не заботится о несоответствии длины каждого элемента входного аргумента, но сохраняет другие данные), поиграть с ними с помощью различных варианты использования, дайте мне знать, если какой-либо из них соответствует вашим потребностям, а затем отредактируйте вопрос, чтобы убедиться, что вы указываете там свои требования (какие порядки массивов вас интересуют и т. д.).
Нет, просмотреть его на телефоне было нормально, мне просто нужно было посмотреть на .d.ts, так как на типы нельзя наводить курсор. Я просто не думал о порядке, когда изначально задавал вопрос. Спасибо, что заметили :) Какова цель extends [any, ...any[]]? Разве это не излишне? И после того, как с ним поигрались, отображение выглядит так, как будто оно работает отлично. Я понятия не имел, как это написать в ТС, лол.






В дальнейшем я буду полностью игнорировать comparator. Я также предполагаю, что вы не хотите обращать внимание на длину каждого элемента массива (поэтому sortArraysTogether([["a","b"], [1,2,3]]) не будет ошибкой, даже если во втором элементе слишком много записей).
Я предполагаю, что вас волнует порядок элементов arrays и тип возвращаемого значения, поэтому sortArraysTogether([["a"],[1],[true]]) должно быть [string[], number[], boolean[]], а не (string | number | boolean)[][]. Это означает, что вы действительно не хотите T[][], даже если бы могли T работать. Действительно, вы не хотите, чтобы тип вывода был простым массивом формы ⋯[], потому что он неупорядочен. Тип вывода должен быть универсальным , то есть это может быть кортеж, который меняется в зависимости от типа ввода.
Наконец, поскольку вас заботит порядок ввода, вы также можете потребовать, чтобы был хотя бы один элемент, поэтому sortArraysTogether([]) должно быть ошибкой.
Учитывая эти требования, sortArraysTogether() должен выглядеть так:
declare function sortArraysTogether<T extends [any, ...any[]]>(
arrays: { [I in keyof T]: T[I][] },
): { [I in keyof T]: T[I][] };
Здесь функция является общей для T, типа каждого элемента arrays. Итак, если вы позвоните sortArraysTogether([[0],["a"],[true]]), то T будет [number, string, boolean]. Я включил T в открытый кортеж [any, ...any[]]. Это дает TypeScript намек на то, что вам важен порядок, и требует, чтобы входные данные содержали хотя бы один элемент.
Типом arrays и типом вывода являются {[I in keyof T]: T[I][]}, тип отображаемого кортежа , который выражает тот факт, что каждый элемент ввода arrays и вывода сам по себе является массивом соответствующего элемента T. Итак, если T равно [A, B, C, D], то тип arrays и возвращаемый тип — [A[], B[], C[], D[]].
Давайте проверим это:
const z = sortArraysTogether([[20, 10, 30], ['bob', 'alice', 'charlie'], [1, 3, 10]]);
// ^ const z: [number[], string[], number[]]
sortArraysTogether([]); // error!
// ~~
// Argument of type '[]' is not assignable to parameter of type '[any[], ...any[][]]'.
Выглядит неплохо.
TypeScript не очень любит синтезировать объединения. Вы можете создать
Tтип элементаarrays(вместо объединения типов элементов), как показано в этой ссылке на игровую площадку . Соответствует ли это вашим потребностям? Если да, то напишу ответ или найду подходящий источник дублирования. Если нет, пожалуйста, отредактируйте, чтобы уточнить, чего не хватает.