简体   繁体   中英

Typescript property type lookup doesn't work with optional key

I have an interface with optional parameter, and I want the return type to be based on whether the user passes this key:

interface Base {
  id: string;
  optional?: string;
}

declare function test<T extends Base>(value: T): T['optional'] extends undefined ? number : string;

test({ id: '3' })

But in the above example, the return type is string . Is there any way to make it work?

 test({ id: '3' }) => return type should be number
 test({ id: '3', optional: '' }) => return type should be string

I think the problem here is that an optional property optional?: string can actually be three different types once it's matched to the generic parameter.

  • string as in { optional: 'foo' }
  • undefined as in { optional: undefined }
  • never as in {}

So in test({ id: '3' }) T['optional'] is never , and T['optional'] extends undefined is falsy.

It's probably simplest to check for the positive case string instead:

T['optional'] extends string ? string : number;

Playground


However, you can avoid generic altogether with a simple overload.

declare function test(value: Base & { optional: string }): string;
declare function test(value: Base): number;

The first signature accepts a Base & { optional: string } which would not match the case where optional is omitted. The second signature catches any other valid Base , which would be the undefined or missing case.

Playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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