Typescript — общий класс только с двумя возможными типами

Я пытаюсь создать универсальный класс, в котором тип свойства должен быть либо строкой, либо числом (поскольку он используется в качестве индекса).

Если я попробую что-то вроде кода ниже, он будет жаловаться, что

TS2536: тип «T» нельзя использовать для индекса типа «{}».

export class GenericClass<T> {
    public selectionMap: {[id: T]: boolean} = {};

    public isSelected(id: T): boolean {
      return !!this.selectionMap[id];
    }

    public toggleSelected(id: T): void {
        if (this.isSelected(id)) {
            delete this.selectionMap[id];
        } else {
            this.selectionMap[id] = true;
        }
        this.onChange();
    }
}

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

Отвечает ли это на ваш вопрос? TypeScript — как представить сигнатуру индекса в виде универсального типа

BizzyBob 22.12.2022 15:39
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
2
1
71
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Почему вы используете дженерики в этом случае? Просто используйте типы, которые вы хотите иметь, или определите тип, который соответствует вашим потребностям:

type Id = number | string;
export class GenericClass {
    public selectionMap: {[id: Id]: boolean} = {};

    public isSelected(id: Id): boolean {
      return !!this.selectionMap[id];
    }

    public toggleSelected(id: Id): void {
        if (this.isSelected(id)) {
            delete this.selectionMap[id];
        } else {
            this.selectionMap[id] = true;
        }
        this.onChange();
    }
}

Хорошее решение, мне в голову не пришло. Но я боюсь, что у него есть одна небольшая проблема. Поскольку этот класс больше похож на util. Мне придется привести результаты каждого метода, вызванного вне этой функции. Потому что мудрая функция всегда будет возвращать число | строка, но я хочу знать, что если я скажу при объявлении, что это используемый номер, он вернет число, а не число | нить. Или я что-то упустил, и это может справиться с этим?

Andurit 22.12.2022 14:24

Кстати, я уже ставлю лайк за это, это определенно решение. Просто не уверен, соответствует ли мой точный сценарий.

Andurit 22.12.2022 14:25

В этом случае ответ от @ mh377 более уместен. Просто с кодом, который вы разместили, не было необходимости использовать общий класс.

Garuno 22.12.2022 14:29
Ответ принят как подходящий

Попробуйте следующее:

export class GenericClass<T = string | number> {}

или

export class GenericClass<T extends string, number> {}

Кроме того, убедитесь, что типы, которые вы используете для вызова класса, имеют строчные буквы string и number. Смотрите этот блог для получения дополнительной информации.

Спасибо, это имеет смысл, я пробовал что-то подобное, но испортил синтаксис, и это не сработало.

Andurit 22.12.2022 14:20

Я только что проверил это, и я все еще получаю ошибки: TS2536: Type 'T' cannot be used to index type '{}'.

Andurit 22.12.2022 14:36

Я не вижу код, который вы используете для вызова этого класса, но это примитивы объектов, то есть использование строчных букв «строка» и «число». Подробности смотрите в этом блоге bobbyhadz.com/blog/….

mh377 22.12.2022 14:40

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