Полный воспроизводимый репозиторий — https://github.com/Liooo/vite-project, просто запустите yarn install && yarn tsc
, чтобы увидеть ошибку.
Я хочу использовать реакцию v18 с Typescript <v5.1, но tsc выдает ошибку TS2786 'MyComponent' cannot be used as a JSX component. Its return type 'string' is not a valid JSX element.
, как показано ниже:
const MyComponent = () => 'x'
function App() {
return (
<>
<div>
<MyComponent />
// ↑
// error TS2786: 'MyComponent' cannot be used as a JSX component.
// Its return type 'string' is not a valid JSX element.
</div>
</>
)
}
// package.json
{
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"typescript": "4.9.5" // <= the error disappears with for example "5.1.6"
}
}
Когда я обновляю машинописный текст до > v5.1, ошибка исчезает.
Пробовал настроить расширение JSX.Element вот так, но пока безуспешно.
если быть точным, то моя цель здесь следующая:
Примечания:
Обертывание строк в такие элементы, как const MyComponent = () => (<>{'x'}</>)
, работает, но я не хочу этого делать, хочу иметь возможность возвращать строку из компонента)
Ошибка должна быть связана с этой проблемой с Microsoft/Typescript
Причина, по которой это работает в версии 5.1+, вероятно, связана с несвязанной проверкой типов между элементами JSX и типами тегов JSX в ответ на эту проблему
Отвечает ли это на ваш вопрос? Как вернуть строку или элемент JSX в компоненте TypeScript React?
См. также Что-то на моем веб-сайте или проекте не работает. Можно просто ссылку на него вставить?
@Фил, да, это работает, но так не должно быть.
Я не понимаю, о чем вы спрашиваете. Да, это была проблема в TypeScript. Да, они это исправили. Как и в случае с любой ошибкой в старом программном обеспечении, если вы не можете обновиться, вам нужен обходной путь.
@Phil наша старая кодовая база сильно ломается при обновлении машинописного текста, требование состоит в том, чтобы использовать реакцию v18, Typescript < v5.1 и разрешать строку (а также число и другие типы в стиле ReactNode) быть действительными как JSX.Element. Я думал, что расширение модуля — это обходной путь, но мне с этим не повезло.
И я думаю, что причина ошибки как раз связана с этой github.com/microsoft/TypeScript/pull/51328
«Я ищу обходной путь»… некоторые из них вам были представлены в предложенном дубликате . Вы пробовали это? Если да, то почему они не удовлетворяют вашим требованиям?
@Phil Ни один из этих вариантов не является тем обходным путем, который я ищу, они предлагают обертывать компонент, а не
Решение состоит в том, чтобы не использовать такое на старой версии TS, насколько сложно его обновить? Обычно это легко
Вы пробовали return "mystring" as unknown as JSX.Element
согласно этому ответу? Вы также не объяснили, почему вы не можете обернуть строку во фрагмент.
по сути это то же самое, что заключить <>{...}</>
. как я уже сказал, я хочу, чтобы JSX.Element принимал строки и другие типы ReactNode в базе кода, как и должно быть.
Это просто невозможно с той версией TypeScript, которую вы используете, и нет, это даже близко не одно и то же. Совершенно неясно, какой ответ вы здесь ищете, но это похоже на простое принятие желаемого за действительное... «Я хочу, чтобы эта конкретная версия TypeScript делала то, что она не может делать без моих изменений»
@Доминик, мы бы сделали это, если бы могли, но у нас есть куча устаревшей кодовой базы, которая резко ломается после обновления ts, и мы решили не делать этого прямо сейчас, поэтому ищем обходной путь :(
@Фил, как я уже сказал, тип обходного пути, который я ищу, другой, я предположил, что расширение модуля может быть таким же способом, как и то, что сделал TypeScript на github.com/microsoft/TypeScript/pull/51328
просто запустить функцию? Зачем пытаться заставить функциональный компонент возвращать строку?
const myStringfunc = (): string => { return 'x' }
...
<div>{ myStringfunc() }</div>
видимо, мне нужно изменить имя функции, чтобы было понятно, что я предлагаю не FC в качестве решения, а обычную функцию, возвращающую строку. Если реальный вариант использования привел к дорогостоящему повторному рендерингу, поднимите его, привяжите к константе, запомните.
в этом примере это не компонент, а статическая функция, я просто сохранил используемое соглашение об именах.
спасибо, но я хочу разрешить отображение строки как элемента JSX по всей базе кода. Причина в том, что это исходное поведение реакции, и мы хотим, чтобы тип работал соответствующим образом, не заключая все вхождения в return <>{stringVar}</>
или return stringVar as unknown as ReactElement
и т. д.
ок, тогда вроде как принял ответ, другого обходного пути, кроме обновления TS, нет.
Нет обходного пути, кроме обновления машинописного текста:
https://github.com/DefiniteTyped/DefinitelyTyped/discussions/69919#discussioncomment-9892117
Пробовали ли вы вместо этого вернуть фрагмент JSX?
return <>some string</>;