Typescript 验证typeguard中的多个类型

Typescript 验证typeguard中的多个类型,typescript,Typescript,是否可以在一个类型保护中验证多个类型?这就是我想要的: interface A { } interface B extends A { foo: number; } interface C extends A { bar: number; } function is<T extends A>(item: A): item is T { if((item as B).foo) // validate as B if((item as A).bar)

是否可以在一个类型保护中验证多个类型?这就是我想要的:

interface A { }

interface B extends A {
  foo: number;
}

interface C extends A {
  bar: number;
}

function is<T extends A>(item: A): item is T {
  if((item as B).foo)
    // validate as B
  if((item as A).bar)
    // validate as A
}
接口A{}
接口B扩展了A{
foo:数字;
}
接口C扩展了{
条:数字;
}
功能为(项目:A):项目为T{
如果((项目为B.foo)
//验证为B
如果((项目为.bar)
//验证为
}
我打算这样使用它:

if(is<B>(item)) {
// do stuff 
}
如果(是(项目)){
//做事
}

如上所述,你想要的是不可能的

静态类型系统是在编译TypeScript代码时使用的。所以这个类型脚本代码:

const item: A = { foo: 123 };
if (is<B>(item)) { console.log(item.foo.toFixed(2)); }
if (is<C>(item)) { console.log(item.bar.toFixed(2)); }
const item: A = Math.random() < 0.5 ? { foo: 123 } : { bar: 456 };
if (is(item)) { console.log(item.foo.toFixed(2)); }
if (is(item)) { console.log(item.bar.toFixed(2)); }
现在至少可以想象,
is()
的实现可以使用第二个参数来确定应该检查哪个属性。事实证明,实现并给出适当的强类型签名是可能的,尽管看到魔术背后的精巧装置可能会令人失望:

type PossibleTypes = B | C;
const props = {
    B: "foo",
    C: "bar"
} as const
type Props = typeof props;

function is<K extends keyof Props>(
    item: A,
    typeName: K
): item is Extract<PossibleTypes, Record<Props[K], number>> {
    const key = props[typeName];
    return ((key in item) && (typeof (item as any)[key] === "number"));
}
但我想这取决于你的用例和气质



哇,谢谢你的详细回答,非常感谢
type PossibleTypes = B | C;
const props = {
    B: "foo",
    C: "bar"
} as const
type Props = typeof props;

function is<K extends keyof Props>(
    item: A,
    typeName: K
): item is Extract<PossibleTypes, Record<Props[K], number>> {
    const key = props[typeName];
    return ((key in item) && (typeof (item as any)[key] === "number"));
}
function isB(item: A): item is B {
    return ("foo" in item) && (typeof (item as any).foo === "number");
}
function isC(item: A): item is C {
    return ("bar" in item) && (typeof (item as any).bar === "number");
}
const item: A = Math.random() < 0.5 ? { foo: 123 } : { bar: 456 };
if (isB(item)) { console.log(item.foo.toFixed(2)); } 
if (isC(item)) { console.log(item.bar.toFixed(2)); }