undefined
undefined

Reputation: 6854

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

Upvotes: 0

Views: 986

Answers (1)

Alex Wayne
Alex Wayne

Reputation: 187024

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

Upvotes: 2

Related Questions