Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Difference between bracket notation property access and Pick utility in TypeScript

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

        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);
        }
    }

}

>Solution :

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:

type SomeType = {
    videoConstraints?: MediaStreamConstraints["video"];
}

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:

this.videoConstraints = videoConstraints!;
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading