首页 > 解决方案 > TypeScript:跨多种类型的接口?

问题描述

所以我从一个端点获取数据,该端点返回一个不同类型的集合,这些类型都具有相同的接口……类似于:

interface CommonInterface {
    public type: string;
    public commonProperty1: integer;
    public commonProperty2: boolean;
}

class Thing1 implements CommonInterface {}

class Thing2 implements CommonInterface {}

然后端点返回CommonInterface[],它是Thing1Thing2实例的混合。其中一个属性CommonInterfacetype鉴别器,它识别它是哪个“事物”。

如何在 TypeScript 中对这种类型结构进行排序?如何告诉 TS 数组是 type CommonInterface,然后告诉它第一项(基于type值)是 a Thing1,第二项是 a Thing2,第三项是 a Thing1

我已经进行了一些搜索,但没有找到任何真正理解这种情况的东西。在此先感谢您的帮助!

标签: typescripttypesinterfacecasting

解决方案


假设您获得了以下类定义:

class Thing1 implements CommonInterface {
    readonly type = "Thing1";
    commonProperty1 = 1;
    commonProperty2 = true;
    thing1Prop = "okay";
}

class Thing2 implements CommonInterface {
    readonly type = "Thing2";
    commonProperty1 = 2;
    commonProperty2 = false;
    thing2Prop = "okay";
}

我倾向于构建用户定义的类型保护函数来表示测试以查看 aCommonInterface是 aThing1还是 aThing2或其他东西。它可能看起来像这样:

type Things = Thing1 | Thing2;
function isThing<T extends Things["type"]>(
    obj: CommonInterface, type: T
): obj is Extract<Things, { type: T }> {
    return obj.type === type;
}

你可能会像这样使用它:

function processCommonInterfaceArray(objs: CommonInterface[]) {
    objs.forEach(c => {
        if (isThing(c, "Thing1")) {
            c.thing1Prop.toUpperCase();
        } else if (isThing(c, "Thing2")) {
            c.thing2Prop.toUpperCase();
        } else {
            // c is some other commonInterface
            c.commonProperty1.toFixed();
        }
    })
}

从中可以看出,编译器使用isThing(c, "Thing1")返回true来得出c必须是 a 的结论,Thing1因此具有 a thing1Prop。这同样适用于isThing(c, "Thing2")Thing2。因为你不能确定所有CommonInterface的对象都是肯定的Thing1Thing2(没有什么能阻止某人拥有一个Thing3that implements CommonInterface),那么你需要在最后一个else子句中做一些事情。


请注意,通常我希望您使用类型的可区分联合之类的东西Things而完全忘记CommonInterface。如果您可以重构您的类型以使端点返回Things[]而不是CommonInterface[],那么您不需要用户定义的类型保护来进行控制流缩小:

function processThings(objs: Things[]) {
    objs.forEach(c => {
        if (c.type === "Thing1") {
            c.thing1Prop.toUpperCase();
        } else {
            c.thing2Prop.toUpperCase();
        }
    })
}

好的,希望有帮助;祝你好运!

Playground 代码链接


推荐阅读