Принудительно ссылаться только на поля, которые существуют для встроенного определения объекта?

Я хочу быстро объявить объект, в котором поля должны быть определенного типа (CSSProperties в этом примере, но в конце я хочу универсальный тип).

Когда я использую индексированный тип (или Record), TS ограничивает значения значений поля-члена правильным типом и выдает ошибки, если я неправильно определяю их содержимое. Но он теряет информацию о том, какие поля были определены, поэтому ссылка на неопределенное поле не приведет к ошибке компиляции, и вызывающая сторона просто получит undefined.

export const simpleStyle = {
  a: {
    margin: 0,
  },
  b: {
    margin: 0,
    wibble: 'blah', // no compile error: BAD
  },
} 

const simpleA = simpleStyle.a;
// causes a compile error: GOOD
// const simpleB = simpleStyle.wibble;

export type CssStyles = { [index: string]: CSSProperties };

export const typedStyle: CssStyles = {
  a: {
    margin: 0,
  },
  b: {
    margin: 0,
    // causes a compile error : GOOD
    // wibble: 'blah',
  },
}

const typedA = typedStyle.a;
// does not cause a compile error
const typedB = typedStyle.wibble;

Как определить этот тип, чтобы Typescript считал ссылки на неопределенные индексы недействительными? Где «определено» определяется содержимым объекта, который я объявляю (я не хочу переопределять все поля в объединении и не хочу определять явный тип).

Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой 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 для повышения производительности приложения путем загрузки модулей только тогда, когда они...
1
0
20
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Если вы хотите применить и ввести и в то же время вывести более конкретный подтип, вам нужно использовать общую функцию.

function createStyles<K extends string>(
  styles: Record<K, CSSProperties>
): Record<K, CSSProperties> {
  return styles
}

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

Это также использует тип утилиты Record для сопряжения ключей со значениями в объекте.

Теперь это работает так, как вы ожидаете:

export const typedStyle = createStyles({
  a: {
    margin: 0,
  },
  b: {
    margin: 0,
    wibble: 'blah', // error
  },
})

const typedA = typedStyle.a;
const typedB = typedStyle.wibble; // error

Детская площадка


Наконец, я добавлю, что команда Typescript работает над новой функцией, чтобы сделать функцию необязательной через оператор satisfies.

Спасибо! Кажется, у меня есть слепое пятно для этих функций «форсирования типов». Есть название техники? Знает ли TS, что эта функция существует только для связи с компилятором? (Значит, после успешной проверки типов он может просто встряхнуть вызов метода, поскольку он ничего не делает?)

Shorn 23.03.2022 23:50

Это просто общая функция, ничего особенного в ней нет. Он существует во время выполнения и практически ничего не делает во время выполнения. Но команда машинописи работает над улучшением этого: github.com/microsoft/TypeScript/issues/47920

Alex Wayne 23.03.2022 23:53

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