在函数中断言字段对象时,Typescript 类型断言不起作用

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

我尝试在函数中的对象字段上使用类型断言,然后使用返回对象(在函数中断言)。

这里有一个例子:

interface MyInterface {
    abc: string;
}

type Abc = "A" | "B";

function assertAbc(v: string): asserts v is Abc {
    if (!["A", "B"].includes(v)) {
        throw Error();
    }
};

const needAbc = (_: Abc) => true;

const shouldBeWithAbcType = () => {
    const myObj: MyInterface = { abc: "A" };

    // Everything that come after this should be an object with abc as type
    assertAbc(myObj.abc);

    // this work as intended, abc is of type Abc
    needAbc(myObj.abc);

    // Return the object
    return myObj;
}

const c = shouldBeWithAbcType();

// c.abc is a string, so this doesn't work, why ?
needAbc(c.abc);

为什么

needAbc(c.abc)
不起作用?

带有示例的 ts 游乐场这里

相同的示例但没有对象(返回 Abc 类型)也可以。

typescript typescript-types
2个回答
0
投票

您可以使用Type Guards。我认为

asserts
关键字是多余的。此外,类型保护函数必须返回
boolean
指示输入是否属于您期望的类型。

function isAbc(v: string): v is Abc {
    if (!["A", "B"].includes(v)) {
        return false;
    }

    return true;
}

游乐场


0
投票

为什么?我猜是因为编译器不够聪明,无法在某个函数内对某个对象的字段进行某种类型断言,超出该函数的范围,从该点开始,该对象的任何地方都会发生这种情况。从技术上讲,我猜它可以,但技术上会很困难,但事实并非如此。 docs 明确指出该断言仅适用于当前范围:

TypeScript 3.7 引入了一个称为“断言签名”的新概念,它对这些断言函数进行建模。第一种类型的断言签名模拟了 Node 断言函数的工作方式。它确保所检查的任何条件对于包含范围的其余部分都必须为真。

因此,断言不仅不会在函数之外进行,甚至不会在条件或 for 循环范围之外进行。

如果您希望它工作,您需要在“shouldBeWithAbcType”外部显式定义您想要的接口,然后告诉编译器这就是“shouldBeWithAbcType”返回的内容,而不是依赖于编译器推断的类型(即“MyInterface”)。示例:

interface MyInterface {
    abc: string;
}

interface MyStrictInterface {
    abc: Abc;
}

type Abc = "A" | "B";

function assertAbc(v: unknown): asserts v is Abc {
    if(typeof(v) !== 'string') throw new Error()
    if (!["A", "B"].includes(v)) {
        throw Error();
    }
};

function assertAbcObject(v: unknown): asserts v is MyStrictInterface {
    if(!v || typeof(v) !== 'object' || !('abc' in v)) throw new Error();
    assertAbc(v.abc)
};

const needAbc = (_: Abc) => true;

const shouldBeWithAbcType = () => {
    const myObj: MyInterface = { abc: "A" };
    assertAbcObject(myObj)
    return myObj;
}

const c = shouldBeWithAbcType();
// Works
needAbc(c.abc);

游乐场

© www.soinside.com 2019 - 2024. All rights reserved.