如何让打字稿知道我的变量不再是未定义的

Jas*_*der 8 typescript

这是我的案例:

我正在使用Remix 加载器,它从 URL 获取参数,但参数定义为string | undefined

如果变量是undefined我想抛出一个重定向

export const loader: LoaderFunction = async ({ params }) => {
  const { myVar } = params; // myVar: string | undefined 
  definedOrRedirect(myVar, "/"); // Checks if undefined
  return fetchSomething(myVar); // myVar: string | undefined
};
Run Code Online (Sandbox Code Playgroud)

有没有办法让打字稿知道如果它没有抛出则myVar不是未定义的?

jca*_*alz 4

您可以创建throwIfUndefined一个断言函数,将其参数类型缩小为不包含undefined在其域中的类型。断言函数具有以下形式的断言类型谓词asserts x is Y作为其返回类型,其中x是函数参数之一的名称,并且是我们缩小到假设函数成功返回的Y子类型。断言函数不能返回定义的值;它们基本上是返回函数。typeof Xxvoid

对于throwIfUndefined,这是执行此操作的正常方法,作为函数语句:

function throwIfUndefined<T>(x: T | undefined): asserts x is T {
    if (typeof x === "undefined") throw new Error("OH NOEZ");
}
Run Code Online (Sandbox Code Playgroud)

您也可以将其编写为箭头函数,尽管您需要使用变量的类型显式注释变量,以便正确进行控制流分析:

const throwIfUndefined: <T, >(x: T | undefined) => asserts x is T = x => {
    if (typeof x === "undefined") throw new Error("OH NOEZ");
}
Run Code Online (Sandbox Code Playgroud)

无论哪种方式都应该有效:

const Index = ({ params }: { params: { myVar: string | undefined } }) => {
    const { myVar } = params // myVar: string | undefined
    // myVar.toUpperCase // <-- error, Object is possibly 'undefined'
    throwIfUndefined(myVar);
    return myVar.toUpperCase() // no error now
}

try {
    console.log(Index({
        params: {
            myVar: Math.random() < 0.5 ? "hello" : undefined
        }
    })) // 50% "HELLO" 
} catch (e) {
    console.log(e); // 50% "OH NOEZ"
}
Run Code Online (Sandbox Code Playgroud)

Playground 代码链接