Есть идеи, почему Typescript ведет себя таким образом с поддержкой серьезности предупреждений пользовательского интерфейса Material?

#javascript #reactjs #typescript #material-ui

Вопрос:

У меня есть проект react, запущенный с помощью Typescript, и я получаю следующую ошибку

Type 'string' is not assignable to type 'Color | undefined'.

Когда у меня бывает что-то подобное…

 const foo = {stuff:"success"}

<MuiAlert
  onClose={handleSnackbarClose} 
  severity={foo.stuff}
>
  Words
</MuiAlert>
 

Тем не менее, код работает нормально, если константа foo является строкой…

 const foo = "success"

<MuiAlert
  onClose={handleSnackbarClose} 
  severity={foo}
>
  Words
</MuiAlert>
 

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

Комментарии:

1. Строковый литерал const известен во время компиляции (гарантируется, что он не изменится), но значения свойств объекта могут изменяться во время выполнения.

2. Чтобы развить ответ Джареда, вы можете объявить, что разрешено на foo const foo = { stuff: "success" } as { stuff: Color | undefined };

Ответ №1:

Базовые типы обрабатываются по — разному в примерах, которыми вы поделились. Более подробно:

 const foo = "success"
 

Этот тип foo сейчас буквально "success" . Typescript знает, что он был установлен в "success" значение и что, поскольку он является константой, он никогда не изменится.

Однако это:

 const foo = { stuff: "success"}
 

…разрешается в тип {stuff: string} . Typescript знает, что это объект с ключом «материал» на нем, но поскольку объекты изменчивы, он не знает, что bar.stuff так будет всегда "success" . Он возвращается к более универсальному string типу.

Ошибка, которую вы получаете, заключается в том , что Color тип, который вы где-то определили, принимает значение "success" , но не принимает никакой строки. Таким образом, первый пример приемлем для компилятора, но он не знает, что второй должен соответствовать тому же набору значений.

Альтернативой было бы сделать что-то вроде этого:

 const foo: {stuff: Color} = {stuff: "success"}
 

Таким образом, Typescript будет знать, что foo stuff поле всегда будет a Color . В качестве бонуса вы получаете автозаполнение, когда начинаете вводить строку, в которой будете хранить foo.stuff .

Комментарии:

1. Ах, в этом есть смысл!! Спасибо вам за понимание!

Ответ №2:

Это связано с тем, что серьезность типизируется как так называемая Literal Type в MUI.
Они определили серьезность, чтобы принимать только объединение нескольких строк.

Проблема с вашим кодом описана в руководстве по машинописи в разделе Буквальный вывод.

foo.stuff имеет только строковый тип, а не литеральный тип «успех», но если вы назначите foo значению напрямую, оно может представлять как строковый тип, так и литеральный тип «успех», что и принимает prop серьезности.

Или более общее: foo является постоянным, но foo.stuff-нет. foo.материал может измениться в любое время и больше не содержать значения, которое вы ему только что присвоили. Поскольку вы явно не ввели foo, для foo.stuff приемлемо любое строковое значение, а не только литеральная строка, которой вы его только что присвоили.