#typescript #jsx #typescript-generics #tsc
#typescript #jsx #typescript-generics #tsc
Вопрос:
Я использую TypeScript в синтаксисе JSX без использования React (или любой другой подобной библиотеки). Для jsxFactory
я использую свою собственную фабрику.
Это самая простая версия того, что я хочу:
<Panel>
<Banner text="FREE OFFER" align="left" />
</Panel>
align
Свойство действует required
только тогда, когда Banner
оно помещено внутрь Panel
.
Banner
может использоваться вне a Panel
, но в этом случае использование align
свойства должно выдавать ошибку.
Я хочу, чтобы это произошло во время компиляции.
Я уже пробовал это на игровой площадке typescriptlang.
declare global {
namespace JSX {
interface ElementChildrenAttribute { children: {}; }
}
}
interface BannerInterface {
title: string,
text: string
}
class Banner<T extends BannerInterface = BannerInterface> {
constructor(props: T) {
//
}
}
interface AlignmentInterface extends BannerInterface {
align: string
}
interface PanelInterface {
adId: string,
children: Banner<AlignmentInterface> // I'm trying to pass the AlignmentInterface to the Banner generic
}
class Panel {
constructor(props: PanelInterface) {
//
}
}
// I want this to throw compile error, as align is not in the BannerInterface
const adBanner = <Banner title="Independent Banner" text="test" align="left" />;
// I also want this to throw as Banner is being used as a children of Panel,
// and for that I want the align prop to be required.
const panelBanner = (<Panel adId="1">
<Banner title="Banner inside Panel" text="test" />
</Panel>);
export default { Panel, Banner };
Комментарии:
1. Я бы предложил тип более высокого порядка, переключите его, что-то вроде
children: Aligned<Banner>
. Немного странно говоритьBanner
, что он может принимать толькоalign
тогда, когда он находится внутриPanel
на уровне типа, потому что что, если вы назначитеconst MyBanner = () => <Banner ... />
, а затем отобразите это на панели?2. Привет @jonrsharpe, спасибо за ваш ответ. Я понял вашу точку зрения. Для моего варианта использования у меня также есть проверка во время выполнения. Итак, если a
Banner
динамически добавляется внутри aPanel
, я создаю исключение во время выполнения, что достаточно хорошо. Но я хочу, чтобы проверка JSX во время компиляции (и предложения по редактированию кода VS) была введена как вложенный шаблон. Кроме того, если я не использую JSX, а просто используюnew Panel(...children: new Banner())
— в этом случае я также хочу, чтобы проверка TS дочерних элементов былаalign
в Banner. Спасибо3. @jonrsharpe, я думаю, что я просто решил это, передав общий синтаксис из JSX, например
<Panel< AlignmentInterface> title="" text="" align="">
. Это выглядит немного странно, но работает! Спасибо за ваши подсказки. 🙂