Проверка того, что значение члена объекта соответствует универсальному типу Typescript

Допустим, мне нужно создать объект на основе потенциальных значений типа. Как мне сузить этот объект?

type Values = {
    foo: boolean,
    bar: string
}

type Properties<Type> = {
    name: keyof Type;
    // I want to narrow values so that it only accepts the matching value from Type
    values: Type[keyof Type][];
};

const properties: Properties<Values>[] = [
    {
        name: 'foo',
        // Should complain because 'false' !== boolean
        values: [true, 'false'],
    },
    {
        name: 'bar',
        // Should be ok
        values: ['hello', 'goodbye'],
    }
];

Площадка TypeScript

Вы привязаны к Properties<Type> структуре { name: string, values: something[] }?

Caleth 13.04.2023 18:18

@Caleth К сожалению, я. Я пытаюсь ввести существующую систему, не переписывая много кода.

Jodi Warren 14.04.2023 10:29
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
2
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

вы можете использовать сопоставленные типы для этого.

Проблема в том, что в настоящее время союз создается на основе возможного значения. Если вместо этого вы сопоставите ключи и создадите тип вывода, как вы хотите, вы получите тип объекта со всеми возможными типами.

Затем, если вы индексируете сопоставленный тип с помощью keyof Type, вы можете получить правильно сопоставленные значения.

Такой тип может работать

type Properties<Type> = {
    [K in keyof Type]: { name: K; values: Type[K][] };
}[keyof Type];

ТС площадка

Более детально детская площадка

Форматирование носит субъективный характер, но, конечно же, никто не хочет смотреть на код с нулевым пробелом между символами, поэтому я пошел дальше и отформатировал код.

zenly 13.04.2023 18:20

Фантастика, спасибо! Итак, в этом случае перед индексацией мы создаем что-то вроде: foo: { name: foo, values: boolean[] }, bar: { name: foo, values: boolean[] }? Как работает индексация? Я изо всех сил пытаюсь понять, что немного.

Jodi Warren 14.04.2023 10:36

да, хороший, создается именно этот тип, в основном он просто объясняет все возможные варианты по ключу. Но нам не нужны ключи, поэтому, если вы обращаетесь к объекту, говоря keyof, он в основном дает вам только значения. У вас может быть тип ValueOf<T>=T[keyof T] Предположим, у нас есть вышеупомянутый тип T. Если вы делаете T['foo'] просто получаете часть foo, поэтому вы делаете T['foo'|'bar' ] вы получаете объединение части foo и части bar, и в обобщенном виде оно становится keyof T и дает T[keyof T] = объединение всех значений

Max 14.04.2023 12:03

Итак, это: A) перебирает объединение? или B) создает объединение, а затем сопоставляет шаблоны TS на основе предоставленного имени?

Jodi Warren 14.04.2023 15:54

На самом деле, я думаю, что последнее, как эта игровая площадка, кажется, иллюстрирует

Jodi Warren 14.04.2023 16:00

Да, вот и все, я думаю, что нет такой вещи, как повторяющийся союз. Его 2 шага. Сначала создайте отображаемый тип. Затем получите доступ к нему с помощью keyof, я думаю, что тонкая часть, которую нужно понять, это то, что keyof создает союз. В этом примере keyof Values ​​- "foo"|"bar". Я добавлю ссылку на игровую площадку машинописного текста с некоторыми деталями, которые должны быть немного более понятными.

Max 14.04.2023 19:02

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

class Property<Type> {
  private name_: keyof Type;
  private values_: Type[keyof Type][]
  private constructor(name: keyof Type, values: Type[keyof Type][])
  {
    this.name_ = name;
    this.values_ = values;
  }
  get name(): keyof Type { return this.name_; }
  get values(): Type[keyof Type][] { return this.values_; }
  static make<Type, K extends keyof Type>(name: K, values: Type[K][]): Property<Type>{
    return new Property<Type>(name, values);
  }
};

ТС площадка

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