Simon Hänisch
Simon Hänisch

Reputation: 4958

Typescript: make optional prop required if generic type is set

I want to do something like

export interface Foobar {
  foo: string;
  bar?: any;
}

export interface Foobar<T> {
  bar: T;
}

, so that bar is an optional prop if no generic type is passed, but has to be of the generic type if one is set... i. e., I want to be able to do

const one: Foobar = { foo: 'foo' }; // bar is not required here
const two: Foobar<number> = { foo: 'foo', bar: 123 }; // `bar` is required here

The suggestion above throws

All declarations of 'Foobar' must have identical type parameters.

Is it possible to achieve this in some other way?

Upvotes: 1

Views: 1311

Answers (1)

jcalz
jcalz

Reputation: 327624

I'm not sure what your use case is, but if you can use a type alias instead of an interface, then you could define Foobar to be something like:

type Foobar<T = never> = {
  foo: string;
} & ([T] extends [never] ? { bar?: any } : { bar: T });

This uses a generic parameter default to set T to never if you don't specify it, and a conditional type to choose either an optional bar or a required bar depending on the type of T. It works the way you wanted:

const one: Foobar = { foo: "foo" }; // bar is not required here
const two: Foobar<number> = { foo: "foo", bar: 123 }; // `bar` is required here

Hope that helps; good luck!

Link to code

Upvotes: 5

Related Questions