У меня есть функция, которая сортирует 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
(вместо объединения типов элементов), как показано в этой ссылке на игровую площадку . Соответствует ли это вашим потребностям? Если да, то напишу ответ или найду подходящий источник дублирования. Если нет, пожалуйста, отредактируйте, чтобы уточнить, чего не хватает.