首页 > 解决方案 > 如何判断一个值是否已设置为未定义或根本没有设置?

问题描述

我试图有一个未设置的变量,它的值可以是number或者undefined它的默认值是完全未设置的。我想检查它是否未设置,并要求设置它。

使用符号时遇到问题。

const unset = Symbol('undefined')

type nething = number | undefined | typeof unset

type x = Exclude<nething, typeof unset>

function notUnset<T extends typeof unset> (t: T): Exclude<T, typeof unset> {
    if (t === unset) throw new Error('is symb')
    return t;
}

let value: number | undefined | typeof unset = unset;
value = 1;

const newValue = notUnset(value);

我在使用“TrulyUndefined”类时遇到了问题:

class TrulyUndefined {}

const unset = new TrulyUndefined();

type nething = number | undefined | typeof unset

type x = Exclude<nething, typeof unset>

function notUnset<T extends TrulyUndefined> (t: T): Exclude<T, TrulyUndefined> {
    if (t instanceof TrulyUndefined) throw new Error('is symb')
    return t;
}

let value: number | undefined | TrulyUndefined = unset;
value = 1;

const newValue = notUnset(value);

有谁知道如何做到这一点?

标签: typescriptundefined

解决方案


你提到了一个约定,我想知道它是不是可能的单子

我认为不可能从单个变量中确定一个值是否未设置,因为您已经说过预期的类型T可以是任何东西,所以我们无法检查一个值是默认值T还是默认值,因为T可能包含默认值。

相反,我建议我们有两个值的配对:我们想要的值和一个布尔标志,它告诉我们它是否设置为非。

type MaybeValue<T> = {
    value: T;
    isSet: true;
} | {
    value?: any;
    isSet: false;
}

通过将其定义为联合类型,我们强制如果isSet为真,则该值不能为空。请注意,它可能是undefined,但前提是T包括undefined

如果isSet是假的,那么value可以是任何东西或什么都不是。

这是与此类型交互的示例类。我将这对设置为一个类属性而不是两个,因为它可以很容易地强制执行这两个是可分配给的有效联合MaybeValue<T>。我还包括了一个getOrElse受链接文章启发的可链接方法。


class MaybeUnset<T extends any> {
    private _maybe: MaybeValue<T>

    // constructor creates empty
    constructor() {
        this._maybe = {
            isSet: false
        }
    }

    // static constructor creates with a value already set
    public static create<T>( value: T): MaybeUnset<T> {
        const obj = new MaybeUnset<T>();
        obj.set( value );
        return obj;
    }

    public set( value: T ) {
        this._maybe = {
            value,
            isSet: true
        }
    }

    public unset() {
        this._maybe = {
            isSet: false
        }
    }

    get isSet(): boolean {
        return this._maybe.isSet;
    }

    public getOrElse<U = T>( fallback: U): T | U {
        if ( this._maybe.isSet ) {
            return this._maybe.value;
        } else {
            return fallback;
        }
    }
}

我希望这是您尝试做的任何事情的坚实起点,但我仍然不完全理解!

游乐场链接


推荐阅读