![](/img/trans.png)
[英]TypeScript 3.9.5- The intersection '…' was reduced to 'never' because property 'usage' has conflicting types in some constituents
[英]Typescript mapped return type: intersection reduced to never, conflicting intersection property
目標:使用映射類型查找返回類型,根據輸入類型制作 function 的返回類型。
問題:由於可區分聯合類型的交集存在沖突,我收到一個錯誤,我在概念上理解這一點,但對如何構造我的類型以實現我的目標一無所知。
Type 'Integration' is not assignable to type 'IntegrationTypeData[T]'.
Type 'IntegrationA' is not assignable to type 'IntegrationTypeData[T]'.
Type 'IntegrationA' is not assignable to type 'never'.
The intersection 'IntegrationA & IntegrationB' was reduced to 'never' because property 'name' has conflicting types in some constituents.
我的類型如下所示:
enum Integrations {
A = 'A',
B = 'B',
}
type IntegrationMap<M extends { [key: string]: any }> = {
[Key in keyof M]: M[Key]
};
type IntegrationA = {
name: Integrations.A,
propertyA: string;
}
type IntegrationB = {
name: Integrations.B,
propertyB: number;
}
type IntegrationData = {
[Integrations.A]: IntegrationA;
[Integrations.B]: IntegrationB;
};
// this resolves to type Integration = IntegrationA | IntegrationB
type Integration = IntegrationMap<IntegrationData>[keyof IntegrationMap<IntegrationData>];
// the function I want to make have a dynamic/mapped return type
const getIntegration = <T extends Integrations>(name: T): IntegrationData[T] => {
// the type of the integrations variable is Integration[]
const integration = integrations.find((i: Integration) => i.name === name);
return integration;
};
// desired usage
// typeof intB = IntegrationB
const intB = getIntegration(Integrations.B);
有人可以幫助我了解如何解決此錯誤以及如何正確鍵入數據,以便我獲得此 function 的動態和類型安全返回類型嗎?
integrations
數組的元素是聯合類型(IntegrationA | IntegrationB)
。
如果您查看arrays 的find()
方法的默認調用簽名,您會看到它返回元素類型(在本例中為IntegrationA | IntegrationB
)或undefined
的值。 所以你返回一個類型的值IntegrationA | IntegrationB | undefined
IntegrationA | IntegrationB | undefined
IntegrationA | IntegrationB | undefined
。 但是由於您的函數的返回類型是IntegrationData[T]
其中T
是傳入的name
參數的類型。編譯器不能確定前者可以分配給后者,所以它會抱怨。
您收到的特定錯誤消息是關於交集類型IntegrationA & IntegrationB
被簡化為never
類型,因為確保您返回的Integration[T]
獨立於T
的唯一方法是您的值既是IntegrationA
又是IntegrationB
,這是不可能的。 最好不要太糾結於錯誤消息。
可以說這里的問題是find()
的返回類型對於您的目的來說太寬了。
幸運的是, find()
有另一個調用簽名,它有可能返回比數組元素類型更窄的類型(但仍然可能是undefined
)。 如果您傳入的回調是用戶定義的類型保護 function ,其返回類型謂詞的形式x is Y
,那么將返回縮小的類型Y | undefined
Y | undefined
。
如果編譯器能夠理解i => i.name === name
充當類型保護 function 並帶有調用簽名(i: Integration) => i is IntegrationData[T]
,那就太好了。 不幸的是,這並沒有發生; TypeScript 不會從實現中推斷類型保護 function 調用簽名。 在某些情況下,在microsoft/TypeScript#38390有一個開放的請求來支持這一點,但目前它不是語言的一部分。 (即使是這樣,在這種情況下的這種推斷也可能超出了它的能力。)
如果你想使用i => i.name === name
作為類型保護 function 你需要這樣注釋:
const getIntegration = <T extends Integrations>(name: T): IntegrationData[T] => {
const integration = integrations.find(
(i: Integration): i is IntegrationData[T] => i.name === name
// annotated ---> ^^^^^^^^^^^^^^^^^^^^^^^^^
);
return integration!;
};
注釋可以讓您大部分時間到達那里。 不過,它仍然沒有消除undefined
。 就編譯器所知, integrations
實際上並沒有IntegrationData[T]
類型的元素。 所以integration
可能是undefined
的。 您可以通過在return
之前編寫if (!integration) throw new Error("OH NO I WAS WRONG")
來明確處理此問題。 或者,如果您確定它實際上不是undefined
,您可以通過使用非空斷言運算符 (!)告訴編譯器。 寫作return integration!
,您聲稱integration
不會undefined
或null
,因此類型的值IntegrationData[T] | undefined
IntegrationData[T] | undefined
可以被視為一個IntegrationData[T]
。
現在它編譯沒有錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.