TypeScript 中括号表示法属性访问和 Pick 实用程序之间的区别

问题描述 投票:0回答:1

我有一个如下所示的界面

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

当我使用 pick 来选择这样的属性之一时

    private videoConstraints: Pick<CameraProps, 'videoConstraints'>;

我在这行代码中遇到了这个错误

        this.videoConstraints = videoConstraints;

输入布尔值 | MediaTrack 约束 |未定义不可分配给类型 Pick 类型“未定义”不可分配给类型“Pick” 

似乎选择从我的类型中删除未定义的内容,但是当我编写如下代码时

    private videoConstraints: CameraProps['videoConstraints'];

一切都很好

完整代码如下

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

}

javascript reactjs typescript next.js interface
1个回答
0
投票

那是因为

Pick
并没有像你想象的那样做。它返回一个复合类型,其中包含从其他类型中选择的属性。它不返回单个选定属性的类型。

请参阅此示例(游乐场):

type Stuff {
    a?: string
    b?: number
}

// The type is { a?: string | undefined }
type T1 = Pick<Stuff, 'a'>

// The type is string | undefined
type T2 = Stuff['a']

所以

选择

评估输入

{ videoConstraints?: MediaStreamConstraints["video"] }

但你已经发现了

CameraProps['videoConstraints']

是你真正需要的。这将评估为

MediaStreamConstraints["video"] | undefined
© www.soinside.com 2019 - 2024. All rights reserved.