Как я могу убедиться, что все элементы в массиве уникальны?

Я создаю среду Linq для школы в Typescript в рамках проекта домашнего задания. У меня проблема с методом Select. Я передаю Select массив свойств, но проблема в том, что Typescript допускает дублирование значений в массиве. Есть ли способ в Typescript или Javascript иметь массив только уникальных значений?

Сейчас метод Select выглядит так:

В интерфейсе:

 Select: <K extends keyof T>(this: Table<T, U>, ...properties: K[]) => Table<Omit<T, K>, Pick<T, K> & U>

Реализация:

    Select: function <K extends keyof T>(this: Table<T, U>, ...properties: K[]): Table<Omit<T, K>, Pick<T, K> & U> {
        let selection = this.data.First.map(entry => pickMany(entry, properties))

        let result = this.data.map(
            first => first.map(entry => omitMany(entry, properties))
            ,
            second => merge_list_types(second.zip(selection))
        )

        return Table(result)
    }

Прямо сейчас можно сказать:

customers.Select("name", "name", "age")

Как и ожидалось, приведенный выше код выдаст мне ошибку типа, потому что 'name' уже выбран.

используйте тип коллекции, который не допускает дублирования

Stultuske 28.05.2019 09:24

Java и Javascript — разные вещи. Пожалуйста, исправьте свой тег.

Level_Up 28.05.2019 09:24

Я сказал Джава? Извините, я имел в виду Javascript, спасибо за исправление

user11534547 28.05.2019 09:33
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
3
182
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете обеспечить уникальность массива в общем виде (по крайней мере, не поддерживаемым общим способом, вы можете делать какие-то сумасшедшие вещи с псевдонимом рекурсивного типа, но они, скорее всего, перейдут от версии к другой).

Мы можем создать условный тип, обеспечивающий уникальность до нескольких элементов, и добавить больше по мере необходимости.

type Omit<T, K extends PropertyKey> = Pick<T, Extract<keyof T, K>>
type IsUnique<T extends any[]> = UK0<T, "Items are not unique", {}>

type Tail<T extends any[]> = ((...a: T) => void) extends (p: any, ...t: infer P) => void ? P : [];
type UK0<T extends any[], TErr, TOk> = T extends [] ? TOk : T[0] extends Tail<T>[number] ? TErr : UK1<Tail<T>, TErr, TOk>
type UK1<T extends any[], TErr, TOk> = T extends [] ? TOk : T[0] extends Tail<T>[number] ? TErr : UK2<Tail<T>, TErr, TOk>
type UK2<T extends any[], TErr, TOk> = T extends [] ? TOk : T[0] extends Tail<T>[number] ? TErr : UK3<Tail<T>, TErr, TOk>
type UK3<T extends any[], TErr, TOk> = T extends [] ? TOk : T[0] extends Tail<T>[number] ? TErr : UK4<Tail<T>, TErr, TOk>
type UK4<T extends any[], TErr, TOk> = T extends [] ? TOk : T[0] extends Tail<T>[number] ? TErr : UK5<Tail<T>, TErr, TOk>
type UK5<T extends any[], TErr, TOk> = T extends [] ? TOk : T[0] extends Tail<T>[number] ? TErr : UK6<Tail<T>, TErr, TOk>
type UK6<T extends any[], TErr, TOk> = T extends [] ? TOk : T[0] extends Tail<T>[number] ? TErr : "Array to big"

class Table<T, U> {
    Select = function <K extends Array<keyof T>>(this: Table<T, U>, ...properties: K & IsUnique<K>): Table<Omit<T, K[number]>, Pick<T, K[number]> & U> {

        return null!;
    }
}

new Table<{ a: 0, b: 0}, {}>().Select("a") //ok
new Table<{ a: 0, b: 0}, {}>().Select("a", "a") // err
new Table<{ a: 0, b: 0}, {}>().Select("a", "b") //ok

Вместо этого лучше было бы фактически использовать тип объекта, поскольку объекты по своей сути не допускают дублирования ключей.

class Table<T, U> {
    Select = function <K extends Partial<Record<keyof T, true>>>(this: Table<T, U>, properties: K): Table<Omit<T, keyof K>, Pick<T, keyof K> & U> {

        return null!;
    }
}

new Table<{ a: 0, b: 0}, {}>().Select({ a: true }) //ok
new Table<{ a: 0, b: 0}, {}>().Select({ a: true, a: true }) // err
new Table<{ a: 0, b: 0}, {}>().Select({ a: true, b: true }) //ok

Я думал просто передать объект в качестве параметра, но я думаю, что учителя предпочли бы этот синтаксис Select("a", "b")github.com/hogeschool/Software-Engineering-Minor

user11534547 29.05.2019 12:19

@IAMTHEBEST Как учитель, я могу сказать вам, что это хороший вопрос. Обычно мы не против, чтобы люди задавали вопросы :-)

Titian Cernicova-Dragomir 29.05.2019 12:54

Я хотел бы вернуться к вам на этом примере, мой учитель придумал другое решение в коридоре. Используя Exclude. Я не знаю, как это реализовать, но это как-то связано с созданием типа массива элементов типа K и исключением уже выбранных значений. Ты хоть представляешь, что он имеет в виду и как это понять?

user11534547 18.06.2019 09:32

@IAMTEBEST Невозможно обойти проблему с псевдонимом рекурсивного типа. Псевдонимы рекурсивного типа (за исключением очень ограниченных сценариев) не допускаются. Вы можете каким-то образом обмануть компилятор, чтобы он позволил вам это сделать, но это а) не рекомендуется б) скорее всего, сломается в будущей версии по мере улучшения проверки рекурсивности (и они действительно GH полны псевдонимов рекурсивных типов, которые работали, но не т больше). Если у вашего учителя есть лучшая версия, мне любопытно ее увидеть, но я сомневаюсь, что она работает для произвольно большого массива.

Titian Cernicova-Dragomir 18.06.2019 09:55

я дам тебе знать

user11534547 18.06.2019 11:48

Другие вопросы по теме