I have a type defined that looks like this:
export type MediaProps = ImageMediaProps | OembedProps;
Then have the types it's referencing defined as the following above that code:
type SharedMediaProps = {
/** Media type */
type: "image" | "oembed";
/** Media source URL */
src: string;
};
type ImageMediaProps = SharedMediaProps & {
/** Image alternate text */
alt: string;
/** Image width */
width: number;
/** Image height */
height: number;
};
type OembedProps = SharedMediaProps & {
/** Enable video autoplay */
autoplay?: boolean;
/** Enable video loop */
loop?: boolean;
/** Allow fullscreen */
allowFullscreen?: boolean;
/** Allow picture-in-picture */
allowPictureInPicture?: boolean;
/** oEmbed title */
title?: string;
};
Then in my React component, I have:
export function Media({
type,
title,
width,
height,
src,
autoplay = false,
loop = false,
allowFullscreen = true,
allowPictureInPicture = true,
}: MediaProps) {
but I'm getting notices saying title
, width
, height
, autoplay
, loop
, allowFullscreen
, allowPictureInPicture
aren't defined.
For example, the specific notice I'm getting is:
Property 'allowFullscreen' does not exist on type 'MediaProps'.ts(2339)
It's also happening on other components I've created.
CodePudding user response:
First, move the type
property into the not shared props, so it can be used to discrimitate the type:
type SharedMediaProps = {
/** Media source URL */
src: string;
};
type ImageMediaProps = SharedMediaProps & {
/** Media type */
type: "image";
/** Image alternate text */
alt: string;
/** Image width */
width: number;
/** Image height */
height: number;
};
type OembedProps = SharedMediaProps & {
/** Media type */
type: "oembed";
/** Enable video autoplay */
autoplay?: boolean;
/** Enable video loop */
loop?: boolean;
/** Allow fullscreen */
allowFullscreen?: boolean;
/** Allow picture-in-picture */
allowPictureInPicture?: boolean;
/** oEmbed title */
title?: string;
};
Then define MediaProps
as union of those types:
type MediaProps = ImageMediaProps | OembedProps;
After all this you still can't deconstruct the property in the paramenter because you have to discriminate the type first:
export function Media(props: MediaProps) {
if(props.type === "image") {
const {alt, width, height} = props;
} else {
const {autoplay, loop, allowFullscreen, allowPictureInPicture, title} = props;
}
}
Demo: https://tsplay.dev/NBkVnm
CodePudding user response:
I believe you'll need to use an intersection type on your MediaProps assignment.
export type MediaProps = ImageMediaProps & OembedProps;