首页 > 解决方案 > TypeScript - 通过为属性提供不同的值来扩展类型

问题描述

我有一种类型:

export type EventItemType = {
  Id: string;
  Event?: any;
};

然后我有另一个类型,它最终将是值EventItemType.Event

export type FooEvent = {
  Amount: number;
};

最终对象将是:

{
    Id: 123,
    Event: {
        Amount: 1
    }
}

稍后,我将遍历这些对象的数组:

events.map((event: EventItemType) => {
    return {
        someOtherKey: event.Event.Amount <-- how do I get TS to know this `Event` is of Type `FooEvent`
    }
})

我有一堆对象创建为EventItemTypes,但当时我不知道Event?: any;类型,只有当我定义FooEvent类型时。我该如何解决这个问题?

标签: typescript

解决方案


// introduce generic type parameter Event
export type EventItemType<Event> = {
  Id: string;
  Event?: Event;
};

export type FooEvent = {
  Amount: number;
};

// initialization with specific FooEvent
const events: EventItemType<FooEvent>[] = [];
events.map((event) => {
    return {
        someOtherKey: event.Event?.Amount // nicely shows proper type
    }
})

最终,您可以执行以下操作以保持any原始类型:

export type EventItemType = {
  Id: string;
  Event?: any;
};

export type FooEvent = {
  Amount: number;
};
// function which takes array of some type T extending EventItemType
function processEvents<T extends EventItemType, F extends (event: T) => any>
(events: T[], f: F) { return events.map(f) };

const events = [{Id: '1', Event: {Amount: 1} as FooEvent}]
processEvents(events, event => ({
  someKey: event.Event?.Amount // works nicely
}))

主要区别在于,在第二种解决方案中,我们具有非常多态的行为,并且第二个函数参数将调整为给定数组的类型。

工作推理的核心是:

  • T extends EventItemType我们说我们得到不相等但扩展的类型,EventItemType这意味着 TS 将缩小我们Event: any的参数类型给定的范围
  • F extends (event: T) => any给定函数适用T但也没有指定输出,但由于extend函数输出也会缩小

推荐阅读