如果参数为空,则打字稿函数返回类型为空

Posted

技术标签:

【中文标题】如果参数为空,则打字稿函数返回类型为空【英文标题】:Typescript function return type null if parameter null 【发布时间】:2019-06-30 10:07:37 【问题描述】:

我想让Typescript知道,如果传递给函数的dbUser参数不为null,那么结果肯定不会为null。

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

基本上,我确定如果 dbUser 参数不为空,则结果也不会为空。如何以这种方式定义函数? 目前,当我使用非空参数调用getUser函数时,它仍然说结果可能为空,我知道肯定不能。

【问题讨论】:

嗨!你可以使用布尔值吗? (比如使用真假)。对我来说,我更喜欢避免处理空值。 【参考方案1】:

有多种选择。您可以使用带有重载的函数声明:

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

您还可以使用箭头函数和类型样式获得重载,但它们看起来更丑:

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)

你也可以使用条件类型:

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)

我会推荐第一个选项,它是最简洁的,并且不像其他两个那样需要类型断言。

【讨论】:

有没有办法从单独的文件中导出和导入函数声明?我选择了第一个解决方案,因为它避免了类型断言,但是一个曾经是 200 行的文件,如果不是更多的话,将会变成 500+,因为现在声明必须保留在函数之前。 @ZenVentzi 认为没有办法,希望用 js 编写代码并使用 d.ts ...

以上是关于如果参数为空,则打字稿函数返回类型为空的主要内容,如果未能解决你的问题,请参考以下文章

打字稿通用承诺返回类型

React 条件渲染组件打字稿

基于可选参数存在而不使用函数重载的打字稿函数返回类型

具有默认参数值的打字稿条件返回类型

没有指定参数的打字稿类型函数

函数的打字稿联合/交集类型