我有一个React组件的接口。那里有一堆属性,但是我希望一个属性影响其他属性。 所以,我有:
export interface IMyAwesomeComponentProps<T = {}> {
className: string
defaultPath?: ISomeOtherInterface<T>
// more properties...
// ...and finally
isDraggable?: boolean
onDrag?: () => {}
}
这个东西是这样实现的:
export class MyAwesomeComponent<T> extends React.Component<IMyAwesomeComponentProps<T>> {
//...
}
所以,我要做的是,当我将“ isDraggable”传递为“ true”时,我希望必需。
要解决此问题,我首先从界面中排除了“ onDrag”功能,并添加了新类型。然后,我创建了一个实用程序类型,该实用程序类型基本上说:“如果“ isDraggable”是正确的,则返回结合了“ TDraggableProps”的接口,否则将接口还给我。 总体看起来像这样:
type TDraggableProps = {
onDrag: () => void
// maybe some more props
}
type Test<I extends ITreeProps> = I['isDraggable'] extends true ? I & TDraggableProps : I
export class MyAwesomeComponent<T> extends React.Component<Test<IMyAwesomeComponentProps<T>>>
Aaaand,这种方法行之有效,但事实并非如此。而且我不知道该如何处理接口中的泛型。
答案 0 :(得分:1)
我将通过创建IDraggable接口来更改您的接口IMyAwesomeComponentProps签名,并将其包含在您的IMyAwesomeComponentProps中。当然,这里假设isDraggable = false
和onDrag is defined
的情况是没有用的...
类似这样的东西:
interface ITest<T = {}> {
a: string;
b: IInner<T>;
isDraggable?: IIsDragble;
}
interface IIsDragble {
onDrag: () => void;
}
const a: ITest = {
a: "dsd",
b: {
valInner: "ssdds",
},
};
const b: ITest = {
a: "dsd",
b: {
valInner: "ssdds",
},
isDraggable: {
onDrag: () => true,
},
};
答案 1 :(得分:1)
您可以使用Discriminated union
type Props = {
isDraggable: true;
onDrag: () => void;
} | {
isDraggable: false;
}
const Component = (props: Props) => {}
Component({ isDraggable: false }); // Ok
Component({ isDraggable: true }); // Error onDrag is missing
Component({ isDraggable: true, onDrag: () => {} }); // Ok
如果您需要添加一些常见的道具,则可以将这些类型作为接口并扩展一些基本接口,也可以将它们提取为单独的类型并加入道具
type Props = {
isDraggable: true;
onDrag: () => void;
} | {
isDraggable: false;
}
type StaticProps = {
className: string;
}
const Component = (props: Props & StaticProps) => {}
Component({ isDraggable: false, className: "123" });
Component({ isDraggable: true, className: "123" }); // Error onDrag is missing
Component({ isDraggable: true, onDrag: () => {}, className: "123" }); // Ok
答案 2 :(得分:1)
我将Props设置为类型,然后将所有通用属性和不同属性的所有界面移开,我认为这种方法看起来干净易懂:
interface Common {
x: number;
y: number;
z: number;
}
interface RequiredB {
a: true;
b: () => {}
}
interface OptionalB {
a: false;
b?: () => {}
}
type Props = Common & (RequiredB | OptionalB);
const obj: Props = {
x: 1,
y: 2,
z: 3,
//a: false, // b is not required now
//a: true, // b is required now
}