Aquí está mi caso:
Estoy usando un cargador Remix que obtiene parámetros de la URL pero los parámetros se definen como string | undefined
Si la variable no está undefined , me gustaría lanzar una redirección
export const loader: LoaderFunction = async ({ params }) => { const { myVar } = params; // myVar: string | undefined definedOrRedirect(myVar, "/"); // Checks if undefined return fetchSomething(myVar); // myVar: string | undefined }; ¿Hay alguna manera de hacer que TypeScript sepa que si no arrojó myVar no está indefinido?
Puede hacer que throwIfUndefined sea una función de aserción para restringir el tipo de su argumento a algo que no incluya undefined en su dominio. Una función de aserción tiene un predicado de tipo de aserción de la forma asserts x is Y como su tipo de devolución, donde x es el nombre de uno de los parámetros de la función, e Y es el subtipo del tipo de typeof X al que limitamos x asumiendo que la función devuelve correctamente . Las funciones de aserción no pueden devolver un valor definido; son básicamente funciones de retorno de void .
Para throwIfUndefined , esta es la forma normal de hacerlo, como una declaración de función:
function throwIfUndefined<T>(x: T | undefined): asserts x is T { if (typeof x === "undefined") throw new Error("OH NOEZ"); }También puede escribirlo como una función de flecha, aunque necesita anotar explícitamente la variable con su tipo para que el análisis de flujo de control se realice correctamente:
const throwIfUndefined: <T, >(x: T | undefined) => asserts x is T = x => { if (typeof x === "undefined") throw new Error("OH NOEZ"); }De cualquier manera debería funcionar:
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" }Puede omitir la definición o la definedOrRedirect y usar una verificación explícita:
export const loader: LoaderFunction = async ({ params }) => { const { myVar } = params; // myVar: string | undefined if (myVar == undefined) { return redirect("/"); } return fetchSomething(myVar); // myVar: string } O puede mantener definedOrRedirect y declararlo con una afirmación como sugiere jcalz :
function definedOrRedirect(variable, path): asserts variable is string { if (variable == undefined) { return redirect(path); } } export const loader: LoaderFunction = async ({ params }) => { const { myVar } = params; // myVar: string | undefined definedOrRedirect(myVar, "/"); return fetchSomething(myVar); // myVar: string }