gpt4 book ai didi

typescript :如何使 bool 值与真/假的有区别的联合对一起工作?

转载 作者:搜寻专家 更新时间:2023-10-30 21:06:22 24 4
gpt4 key购买 nike

我有一个界面

interface IData {
importantData: string
}

我想添加 isLoading那里的旗帜。如果isLoading = false , 然后是 importantData已加载并且肯定必须在那里。但是,如果 isLoading = true , 然后 importantData可能存在,也可能不存在。

interface ILoadedData extends IData {
isLoading: false
}

interface ILoadingData extends Partial<IData> {
isLoading: true
}

所以,我的最终类型是这些的联合:

type IDataWithLoading = ILoadedData | ILoadingData

如果我尝试使用 bool 字面值效果很好

const a:IDataWithLoading = ({ isLoading: false, importantData: 'secret' })
const b:IDataWithLoading = ({ isLoading: false }) // the only error, nice
const c:IDataWithLoading = ({ isLoading: true })
const d:IDataWithLoading = ({ isLoading: true, importantData: 'secret' })

但是,在编译时我不知道是否正在加载,所以:

const random = Math.random() > 0.5
const e:IDataWithLoading = ({ isLoading: random, importantData: 'secret' }) // doesn't work

它提示类型不兼容。这是有道理的,因为我为 true 声明了案例和 false , 不适用于 boolean .但是,我涵盖了 boolean 的所有可能情况。 ,所以我觉得 TypeScript 可以理解这一点,我觉得我做错了什么。

如果我声明 boolean然而,明确地,

interface ILoadingData extends Partial<IData> {
isLoading: boolean
}

它将匹配 isLoading = falsePartial<IData> ,这不是我想要的。我该怎么办?

最佳答案

更新:2019-05-30 随着 TypeScript 3.5 的发布,这应该由 smarter union type checking 解决.以下适用于 3.4 及以下版本:


这是一个已知的 limitation of TypeScript .编译器不会尝试将联合传播到属性中。通常这样的传播不会发生(例如,{a: string, b: string} | {a: number, b: number} 不能减少到 {a: string | number , b: string | number} 或其他更有用的东西)。即使在像您这样可以做某事的情况下,编译器做出努力也不符合成本效益。通常,此类情况归结为手动引导编译器完成可能的状态。

例如,你可以试试这个:

interface ILoadedDataButNotSureYet extends IData {
isLoading: boolean;
}

interface ILoadedData extends ILoadedDataButNotSureYet {
isLoading: false
}

因此 ILoadedDataButNotSureYet 确实加载了数据,但 isLoading 可能是 truefalse。然后,您可以将 IDataWithLoading 表示为:

type IDataWithLoading = ILoadedDataButNotSureYet | ILoadingData;

这等同于您的原始定义,但祝您好运,让编译器注意到这一点。无论如何,您提到的所有特定实例仍然有效:

const a: IDataWithLoading = ({ isLoading: false, importantData: 'secret' })
const b: IDataWithLoading = ({ isLoading: false }) // the only error, nice
const c: IDataWithLoading = ({ isLoading: true })
const d: IDataWithLoading = ({ isLoading: true, importantData: 'secret' })

但最后一个也有效:

const random = Math.random() > 0.5
const e: IDataWithLoading = ({ isLoading: random, importantData: 'secret' }) // works

您可能想要也可能不想实际更改 IDataWithLoading。另一种方法是保留原始定义,然后对编译器进行足够大的打击,直到它明白您的代码是安全的。虽然它并不漂亮:

const eLit = { isLoading: random, importantData: 'secret' };
const e: IDataWithLoading = eLit.isLoading ?
{...eLit, isLoading: eLit.isLoading} : {...eLit, isLoading: eLit.isLoading};
// works, but is ugly

哎呀。这里我们使用 object spread复制属性,以及一个单独的 isLoading 属性来利用 type guarding当您检查 eLit.isLoading 时会发生这种情况。三元运算符是多余的(“then”和“else”子句是相同的)但编译器得到消息,在每种情况下,值都匹配 IDataWithLoading。正如我所说,糟糕。


最后,您可以决定自己比编译器更聪明,然后使用 type assertion让它安静下来。这样做的好处是不会让你跳来跳去,缺点是编译器不会帮助你在这里保持类型安全:

const e = { 
isLoading: random,
importantData: 'secret'
} as IDataWithLoading; // Take that, compiler!

如何进行取决于您。希望有所帮助;祝你好运!

关于 typescript :如何使 bool 值与真/假的有区别的联合对一起工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52858273/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com