简体   繁体   English

挑嵌套型 TypeScript

[英]Pick nested type TypeScript

I have a single type generated from a Swagger API definition.我有一个从 Swagger API 定义生成的单一类型。

Each API endpoint has it's API response nested in the Endpoints type.每个 API 端点都有嵌套在 Endpoints 类型中的 API 响应。 Currently I am accessing like this:目前我正在访问这样的:

type Endpoint1Return = Endpoints['/endpoint1']['get']['responses']['200']['content']['application/json']
type Endpoint2Return = Endpoints['/endpoint2']['get']['responses']['200']['content']['application/json']

I want a utility type to pick the nested application/json key for each endpoint.我想要一个实用程序类型来为每个端点选择嵌套的application/json键。 Something like:就像是:

type Endpoint1Return = PickEndpoint<'/endpoint1'>

This is difficult because TS doesn't know that each key of Endpoints has the same child keys for get , responses , 200 etc.这很困难,因为 TS 不知道Endpoints的每个键都有相同的子键用于getresponses200等。

Can anyone think of a way to express this?有人能想出一种表达方式吗?

Given your updated question, I'd say this is a bug in TypeScript, as reported in microsoft/TypeScript#27709 .鉴于您更新的问题,我会说这是 TypeScript 中的一个错误,如microsoft/TypeScript#27709中所述。 It seems that the compiler does not properly evaluate a constraint for nested generic lookup types like Endpoints[K][L]["responses"] .似乎编译器没有正确评估嵌套通用查找类型(如Endpoints[K][L]["responses"]的约束。 That sub-property lookup type seems to mess things up, as you noticed:正如您所注意到的,该子属性查找类型似乎把事情搞砸了:

type PickEndpointWithMethod<K extends keyof Endpoints, L extends keyof Endpoints[K]> =
    Endpoints[K][L]['responses']['200']['content']['application/json']; // error!
// Type '"responses"' cannot be used to index type 'Endpoints[K][L]'.
// Type '"200"' cannot be used to index type 'Endpoints[K][L]["responses"]'.
// Type '"content"' cannot be used to index type 'Endpoints[K][L]["responses"]["200"]'.
// Type '"application/json"' cannot be used to index type 
//   'Endpoints[K][L]["responses"]["200"]["content"]'.

That bug does not seem to be scheduled for fixing anytime soon.该错误似乎没有计划在短期内修复。


As a workaround, you could calculate the constraint of an indexed access yourself, and use the Extract utility type to hint to the compiler that the lookup type does meet that constraint:作为一种解决方法,您可以自己计算索引访问的约束,并使用Extract实用程序类型向编译器提示查找类型确实满足该约束:

type Idx<T, K extends keyof T> = Extract<T[K], T extends any ? T[keyof T] : never>;

Here, we are assuring the compiler that T[K] will extend T[keyof T] even if T is a union of things.在这里,我们向编译器保证T[K]将扩展T[keyof T] ,即使T是事物的联合。 (The T extends any? T[keyof T]: never construction uses distributive conditional types to do so). T extends any? T[keyof T]: never构造使用分配条件类型来这样做)。 Then we can replace, Endpoints[K][L] with Idx<Endpoints[K], L> , like so:然后我们可以将Endpoints[K][L]替换为Idx<Endpoints[K], L> ,如下所示:

type PickEndpointWithMethod<K extends keyof Endpoints, L extends keyof Endpoints[K]> =
    Idx<Endpoints[K], L>['responses']['200']['content']['application/json']; // okay

Let's see if it works:让我们看看它是否有效:

type Endpoint1Return = PickEndpointWithMethod<'/endpoint1', 'get'>
// type Endpoint1Return = "https://example.com/foo"
type Endpoint2Return = PickEndpointWithMethod<'/endpoint2', 'post'>
// type Endpoint2Return = "https://example.com/bar"

Looks good!看起来不错!

Playground link to code Playground 代码链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM