[Vuejs]-How to conditionally assert a type to a variable inside a function based on type of an argument passed to this function in Typescript?

1๐Ÿ‘

โœ…

I need foo() to return X when passed argument A, and Y when passed argument B"

This almost always means you want function overloads.

// for example
function foo(arg: A): X
function foo(arg: B): Y

function foo(arg: A | B): X | Y {
  if (arg.type === 'a') return { x: true }
  return { y: true }
}

Your case is only slightly more complicated.

export default function useFetch<T>(
  options?: { defaultValue?: undefined }
): { fetchedData: Ref<T | undefined> }

export default function useFetch<T>(
  options: { defaultValue: T }
): { fetchedData: Ref<T> }

export default function useFetch<T>({
    defaultValue,
}: {
    defaultValue?: T;
} = {}) {
    return { fetchedData: ref(defaultValue )}
}

The first overload:

export default function useFetch<T>(
  options?: { defaultValue?: undefined }
): { fetchedData: Ref<T | undefined> }

accepts:

useFetch<MyType>()
useFetch<MyType>({})
useFetch<MyType>({ defaultValue: undefined })

And returns Ref<T | undefined>


The second overload:

export default function useFetch<T>(
  options: { defaultValue: T }
): { fetchedData: Ref<T> }

accepts:

useFetch<MyType>({ defaultValue: somethingHere })

and returns Ref<T>.


And lastly your implementation is now very simply:

export default function useFetch<T>({ defaultValue }: { defaultValue?: T } = {}) {
    return { fetchedData: ref(defaultValue )}
}

Which works with a default value:

const { fetchedData } = useFetch<{ foo: string }[]>({ defaultValue: [] });
fetchedData.value[0]; // fine

And without it might be undefined:

const { fetchedData } = useFetch<{ foo: string }[]>();
fetchedData.value[0]; // error as expected

See playground

๐Ÿ‘คAlex Wayne

Leave a comment