TypeScript 在Map类型中使用未定义作为判别器,当涉及到原始交集时,会产生错误的类型,

rqqzpn5f  于 2个月前  发布在  TypeScript
关注(0)|答案(2)|浏览(48)

TypeScript版本: 2.2.0
代码

// A *self-contained* demonstration of the problem follows...
type DeepReadonly<T> = {
    readonly [K in keyof T]: DeepReadonly<T[K]>;
}

interface FieldBrand {
    " do not use ": void;
}

type FieldId = number & FieldBrand;

interface DefOne {
    field: string | FieldId;
    kind: string;
}

interface DefTwo {
    field?: undefined; // Allow discriminant checks on 'field'
    value: string;
}

type Def = DefOne | DefTwo;

interface State {
    a?: Def;
    b?: Def;
}

type ROState = DeepReadonly<State>;

function lookupName(f: FieldId): string {
    return "";
}

function remapFieldsToNames(channels: ROState): ROState {
    const newState: State = {};
    for (const k of Object.keys(channels)) {
        const key = k as keyof ROState;
        const ch = channels[key];
        let replacement: ROState[typeof key] | undefined = undefined;
        if (ch) {
            if (ch.field) {
                const f = ch.field;
                if (typeof f === "number") {
                    f; // Should be FieldId or number, not never!
                    replacement = { ...ch, field: lookupName(f) };
                }
                else if (typeof f === "string") {
                    f; // correct
                }
            }
        }
        newState[k] = replacement || channels[k];
    }
    return newState;
}

预期行为:

上述代码中没有类型错误,并且在typeof f === "number"检查之后的f既可以是数字也可以是FieldId

实际行为:

replacement = { ...ch, field: lookupName(f) };存在类型错误,而f的类型是never

fruv7luv

fruv7luv1#

这里还有一些奇怪的操作,DeepReadonly 在函数体内部的 quickinfo 中省略了通用参数,这可能与相关/应该被调查:

jtw3ybtb

jtw3ybtb2#

DeepReadonly 和带标签的数字之间的奇怪之处实际上导致了每次我试图将深度只读结构分配给普通结构时,类型不兼容。

相关问题