I have an interface like below
export type CameraProps = Omit<React.HTMLProps<HTMLVideoElement>, "ref"> & {
audio?: boolean;
audioConstraints?: MediaStreamConstraints["audio"];
mirrored?: boolean;
screenshotFormat?: "image/webp" | "image/png" | "image/jpeg";
//between 0 & 1
screenshotQuality?: number;
videoConstraints?: MediaStreamConstraints["video"];
fullScreenRecord?: boolean;
screenshotDimensions?: ScreenshotDimensions;
setImageSrc?: Dispatch<SetStateAction<string>>;
overlay?: boolean;
}
when I use pick to pick one of this property like this
private videoConstraints: Pick<CameraProps, 'videoConstraints'>;
I got this error in this line of my code
this.videoConstraints = videoConstraints;
Type boolean | MediaTrackConstraints | undefined is not assignable to type Pick<CameraProps, "videoConstraints">
Type undefined is not assignable to type Pick<CameraProps, "videoConstraints">
it seems pick remove undefined from my type but when I write the code like below
private videoConstraints: CameraProps['videoConstraints'];
every thing is fine
The full code is like below
import React, {Dispatch, SetStateAction} from "react";
export type ScreenshotDimensions = {
width: number;
height: number;
}
export type CameraProps = Omit<React.HTMLProps<HTMLVideoElement>, "ref"> & {
audio?: boolean;
audioConstraints?: MediaStreamConstraints["audio"];
mirrored?: boolean;
screenshotFormat?: "image/webp" | "image/png" | "image/jpeg";
//between 0 & 1
screenshotQuality?: number;
videoConstraints?: MediaStreamConstraints["video"];
fullScreenRecord?: boolean;
screenshotDimensions?: ScreenshotDimensions;
setImageSrc?: Dispatch<SetStateAction<string>>;
overlay?: boolean;
}
export type Maybe<T> = NonNullable<T> | undefined;
export type VideoStatus = 'play' | 'error' | 'wait';
class CameraManager {
private setVideoStatus: Dispatch<SetStateAction<VideoStatus>>;
private videoRef: MutableRefObject<HTMLVideoElement | null>;
private audio: Maybe<boolean>;
private videoConstraints: CameraProps['videoConstraints'];
private audioConstraints: CameraProps['audioConstraints'];
private fullScreenRecord: Maybe<boolean>;
constructor({
audio,
setVideoStatus,
fullScreenRecord,
videoConstraints,
videoRef,
audioConstraints
}: Pick<CameraProps, 'audio' | 'fullScreenRecord' | 'videoConstraints' | 'audioConstraints'> & {
setVideoStatus: Dispatch<SetStateAction<VideoStatus>>,
videoRef: MutableRefObject<HTMLVideoElement | null>
}) {
this.setVideoStatus = setVideoStatus;
this.videoRef = videoRef;
this.fullScreenRecord = fullScreenRecord;
this.videoConstraints = videoConstraints;
this.audioConstraints = audioConstraints;
this.audio = audio;
this.requestUserMedia();
}
private async requestUserMedia() {
const portrait = window.matchMedia("(orientation: portrait)").matches;
try {
this.setVideoStatus('play');
const constraints: MediaStreamConstraints = {
video: this.fullScreenRecord ? {
aspectRatio: portrait ? document.documentElement.clientHeight / document.documentElement.clientWidth : document.documentElement.clientWidth / document.documentElement.clientHeight,
...(typeof this.videoConstraints === 'object' ? this.videoConstraints : undefined),
} :
typeof this.videoConstraints === 'object' ? {
...this.videoConstraints
} : true,
};
if (this.audio) {
constraints.audio = this.audioConstraints || true;
}
const stream = await navigator.mediaDevices.getUserMedia(constraints);
if (!this.videoRef.current) {
return;
}
this.videoRef.current.srcObject = stream;
return stream;
} catch (e) {
this.setVideoStatus('error');
if (e instanceof Error) {
// Handle specific errors here
}
console.log(e);
}
}
}
2
Answers
That’s because
Pick
doesn’t do what you seem to believe it does. It returns a composite type with properties selected from another type. It doesn’t return a type of a single selected property.See this example (playground):
So
evaluates to type
but you already discovered that
is what you actually need. That will evaluate to
In your type declaration, you make
videoContraints
optional with the?
.Pick constructs a new type from picking keys from another type, so you are essentially telling it to create this type with an optional property:
When you assign a property to a different type which requires an optional property created by the Pick, it throws an error, whereas using the bracket notation is more lenient.
To use the Pick type, you can use
!
to assert it’s defined: