1

这是我的界面:

interface Responses {
  200:{
    foo:number;
  };
  204:{
    bar:number;
  };
}

我可以获得如下任何属性类型:

type TypeFor200 = Responses['200'];

但是我想让它成为有条件的,这样如果200接口中不存在属性,它应该返回 for 的类型204,如下所示:

type AnyType= Responses extends 200 ? Responses['200'] : Responses['204'] ;

如果两者都200存在204,则上面的示例将起作用,否则将抛出一个错误,抱怨该属性不存在。

请注意,我无法更改Responses界面,因为它位于自动生成的文件中。

我该怎么做呢?

4

1 回答 1

2

The conditional type you're going for seems to be a red flag for me. I can't think of a construct where this would be useful or necessary. TypeScript already errors when you try to access a property that does not exist on an interface.

interface Responses {
  200: {
    foo: number
  }
}

type NoContentResponse = Responses['204'];
                                   ^^^^^
              Property '204' does not exist on type 'Responses'.

TypeScript Playground

So you should just annotate the types correctly or break down your types so that you can use each fragment and compose them as necessary as opposed to use a conditional type like what you're trying to go for. However I can't think of everything so maybe you really have a use case for a conditional type.

The conditional you want is <key> extends keyof <interface>. This checks for the existence of a key. It would have to be constructed into a generic type. Something like this:

type Foo<A, B, C> = B extends keyof A ? A[B] :
                    C extends keyof A ? A[C] :
                    undefined;

An example with the resultant types is below:

interface OkResponse {
  200:{
    foo:number;
  };
}

interface NoContentResponse {
  204:{
    bar:number;
  };
}

interface NotAResponse {}

type OkAndNoContent = OkResponse & NoContentResponse;
type NoContent = NoContentResponse;

type Foo<A, B, C> = B extends keyof A ? A[B] :
                    C extends keyof A ? A[C] :
                    undefined;

type TypeForOk = Foo<OkAndNoContent, 200, 204>; // { foo: number; }
type TypeForNoContent = Foo<NoContent, 200, 204>; // { bar: number; }
type TypeForNotAResponse = Foo<NotAResponse, 200, 204> // undefined

TypeScript Playground

You can't do extends keyof outside of a generic type because TypeScript has enough type information to give you an error, another reason why this seems to be a red flag for me:

interface NoContentResponse {
  204:{
    bar:number;
  };
}

type TypeForNoContent = '200' extends keyof NoContentResponse ?
  NoContentResponse['200'] : NoContentResponse['204'];
                    ^^^^^
 Type '"200"' cannot be used as an index type.

TypeScript Playground

于 2021-10-16T10:45:26.273 回答