Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript function return type null if parameter null

I want to let Typescript know that if the dbUser parameter passed to the function is not null, then that the result will not be null for sure.

type GetUser = (dbUser: DbUser | null) => GqlUser | null; 
const getUser: GetUser = (dbUser) => {
  if(!dbUser) return null;
  return ... //gql user
};

const dbUser = { ... some fields} //not null for sure
getUser(dbUser) //here I want typescript to know that the result will not be null

Basically, I know for sure that if dbUser parameter is not null, the result won't be either. How can I define the function in such a way? Currently, when I call the getUser function with non-null parameter, it still says that the result could be null, which I know for sure can't.

like image 421
ZenVentzi Avatar asked Feb 06 '19 12:02

ZenVentzi


1 Answers

There are several options. You can use a function declaration with overloads:

function getUser(dbUser: null) : null;
function getUser(dbUser: DbUser) : GqlUser;
function getUser(dbUser: DbUser | null) : GqlUser | null;
function getUser(dbUser: DbUser | null): GqlUser | null {
    if(!dbUser) return null;
    return null! //gql user
} 

const dbUser =  null! as DbUser
getUser(dbUser) // GqlUser

You can also get overloads with the arrow function and type style but they look uglier:

type GetUser = {
    (dbUser: null) : null;
    (dbUser: DbUser) : GqlUser;
    (dbUser: DbUser | null) : GqlUser | null;
} 
const getUser = ((dbUser: DbUser | null): GqlUser | null => {
   if(!dbUser) return null;
   return null! //gql user
}) as GetUser 

const dbUser =  null! as DbUser
getUser(dbUser)

You could also use conditional types:

type GetUser = <T extends DbUser | null>(dbUser: T) => T extends DbUser ? GqlUser : null;
const getUser: GetUser = (dbUser) => {
    if (!dbUser) return null;
    return {} as any // assertions will be required to get a value into the conditioanl type 
};

const dbUser = null! as DbUser //not null for sure
getUser(dbUser)

I would recommend the first option, it's the cleanest and requires not type assertions unlike the other two.

like image 165
Titian Cernicova-Dragomir Avatar answered Sep 22 '22 10:09

Titian Cernicova-Dragomir