是否可以在TypeScript中结合用户定义的类型警卫?

是否可以在TypeScript中结合用户定义的类型警卫?

问题描述:

鉴于是否可以在TypeScript中结合用户定义的类型警卫?

type Maybe<T> = T | undefined; 

class Obj { 
    jbo: Maybe<Jbo>; 
} 

,是可以定义给定一个o: Maybe<Obj>断言类型都oo.jbo的功能?

我喜欢思考的东西:

function everythingIsDefined(o: Maybe<Obj>):o is Obj && o.jbo is Jbo { 
    // checks in here 
} 

用户定义的键盘锁只能返回一个x is T。幸运的是,你可以在你选择的T中使用联合和交叉点。因此,例如:

function everythingIsDefined(o: Maybe<Obj>): o is Obj & {jbo: Jbo} { 
    return typeof o !== 'undefined' && typeof o.jbo !== 'undefined'; 
} 

everythingIsDefined功能断言输入是一个Obj(相对于未定义),一个对象,其jbo属性是一个Jbo(相对于未定义)。所以,你可以使用它像这样:

if (everythingIsDefined(obj)) { 
    console.log(obj.jbo.toString()) // no error 
} 
+1

很好的交点 –

+0

这真棒,谢谢! – gen

呀,你可以拉其关闭:

type Maybe<T> = T | undefined; 
type DeepMaybe<T> = { [K in keyof T]: Maybe<T[K]> }; 

class Obj { 
    jbo: Jbo; 
} 

function everythingIsDefined<T>(o: DeepMaybe<T>): o is T { 
    return false; 
} 

然后:

let obj: DeepMaybe<Obj> = {} as Obj; 
if (everythingIsDefined(obj)) { 
    // type of obj.jbo is Jbo 
} else { 
    // type of obj.jbo is Maybe<Jbo> 
} 

code in playground

说明:
根据您提供的类型(即Obj.jbo: Maybe<Jbo>),可能没有办法实现这一点。
相反,类Obj需要将其属性定义为实际类型,但如果您将变量键入为DeepMaybe<Obj>(或其他任何内容而不是Obj),那么您会得到同样的结果。

现在的区别是,因为DeepMaybe是一种映射类型,您可以更好地控制如何创建类型警卫。

+0

你从'也许'改变Obj.jbo'的'类型'Jbo'。为什么? – jcalz

+0

@jcalz我编辑了我的答案。这是否解释了它? –

+0

是的,我明白你现在说的话。这是一个处理更普遍情况的简便方式,但我认为OP的问题可以更直接地回答。 – jcalz