我有一个案例,我经常同时检查 bool 值和另一个联合类型的值。虽然它们在逻辑上是相关联的,并且可以假设只检查一个,但我需要检查两个,以便 TS 编译器知道这两种类型。
let multiple: boolean
let value: Array<string> | string
...
if (multiple && isArray(value)) {
// TS knows multiple === true and value is an Array
}
有没有一种方法可以编写类型检查函数,其中类型谓词断言多个值?
像这样:
// Not valid Typescript
function isMulti (
multi: boolean,
value: Array<string> | string
): (multi is true) && (value is Array<string>) {
return multi && isArray(value)
}
在大多数情况下,我只需检查 isArray
就可以解决问题,但在某些情况下,我想重复使用上述检查。这可能吗?
回应@kaya3:
为了给出更准确的用例,我有类似下面的内容:
我可以将 multiple
和 value
分配给具有 DiscriminatedUnion 类型的对象,但这增加了比我认为这需要的更多的复杂性。
type ValueType<M extends boolean> = M extends true ? Array<string> : string;
interface PropTypes<M extends boolean> {
multiple: M,
// more properties
}
type DiscriminatedUnion = {
multiple: true,
value: Array<string>
} | {
multiple: false,
value: string
}
function myFunction<M extends boolean>({
multiple
}: PropTypes<M>) {
let value: ValueType<M>;
// ... later
if (multiple) {
// TS will not assert the type of `value` here
}
// Trying discriminated union
// TS Error: Type '{ multiple: boolean; value: string | string[]; }' is not assignable to type '{ multiple: false; value: string; }'
let obj: DiscriminatedUnion = {
multiple,
value
}
}
最佳答案
目前无法通过这种方式解决您的问题; @jcalz 有用地指出有一个开放的 feature request为了它。也就是说,您的问题可能以不同的方式得到更好的解决。
对于几乎任何问题,例如“我有这两个值,我如何告诉 Typescript 它们的类型是相关的?”,答案是将它们作为对象中的属性放在一起。然后你可以使对象的类型成为一个可区分的联合,这样对其中一个属性的测试可以缩小整个对象的类型。
type DiscriminatedUnion =
| {multiple: false, value: string}
| {multiple: true, value: string[]}
declare let obj: DiscriminatedUnion;
if(obj.multiple) {
// here, obj.value is narrowed to string[]
obj.value
}
关于typescript - Typescript 中的多种类型谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69831102/